2

I have a working queueable callout, and working tests using static resource callout mock

I can successfuly run basic assertions on the mock response body and status. However, the callout method in my queueable class should also write the response code back to a custom object record. In unit tests, those assertions fail, but in actual usage, the code works properly and the response code is written back to the custom object record.

The unit tests seem to stop as soon as the mock response is returned, and doe not complete the rest of the method. Is that normal behavior? I cant find anything that indicates it should be.

This is the method that does the callout, in the queueable class.

public static void callOER(string currencyISO, string effectiveDate, ID recordId){
    HttpRequest req = new HttpRequest();
    req.setEndpoint('callout:OpenExchangeRates/historical/'+ effectiveDate +'.json?base=USD&symbols='+ currencyISO +'&app_id=' + appId);
    req.setMethod('GET');
    req.setHeader('Content-Type', 'application/json');
    Http http = new Http();               
    HTTPResponse res = http.send(req);
    System.debug(res.getBody());     
    System.debug('response code = ' + res.getStatusCode());                   
    string response = res.getBody();         
    OERResponse obj = (OERResponse)JSON.deserialize(response, OERResponse.class); 

    IF(recordId != NULL){
    Integration_Bus__c request = [Select Id, Status__c FROM Integration_Bus__c Where Id =: recordId];
    string status = res.getStatus();
        IF(status == 'OK'){
            request.Status__c = 'success';
            request.Response_Code__c = string.valueOf(res.getStatusCode());               
            IF (obj.rates.get(currencyISO) != null ){
                request.exchange_rate__c = obj.rates.get(currencyISO);
            }
        }
        ELSE{
            request.Status__c = 'error';
            request.Error_Message__c = res.getBody();
            request.Response_Code__c = string.valueOf(res.getStatusCode());                
        }
        request.Processed_Time__c = datetime.now();
    update request;
    }

}

the update request DML should set status to 'success' and set response_code__c to 200.

here is my test method

   @isTest static void validateExchangeRateQueueable_Success() {

        opportunity o = [select Id, Name, stageName, CurrencyIsoCode, CloseDate from Opportunity where name = 'testOpp' ];            
        system.debug('opp name = ' + o.Name);
        StaticResourceCalloutMock mock = new StaticResourceCalloutMock();
        mock.setStaticResource('test_OpenExchangeRate_Response');
        mock.setStatusCode(200);
        mock.setStatus('OK');
        mock.setHeader('Content-Type', 'application/json');
        Test.setMock(HttpCalloutMock.class, mock); 
        o.StageName = 'Acceptance with Paperwork';
        update o;
        integration_bus__c ib = [Select Id, Response_Code__c, Status__c FROM Integration_Bus__c WHERE Record_to_Process__c =: o.Id];
        system.debug('ib id = ' + ib.Id);
        system.debug('ib response code = ' + ib.Response_Code__c );
        system.debug('ib status = ' + ib.Status__c );
        // system.assert(ib.Response_Code__c == '200');
        //system.assertEquals(ib.Response_Code__c, '200');
    }

in my debug logs, i see

  • response code = 200
  • the response json from my mock
  • ib id = a3l4F0000000379QAA
  • ib response code = null
  • ib status = started

status__c is set to 'started' by the process that queues up the callout. the callout on the queueable class should update status to 'success' or 'error', and writes the response code back to the integration_bus__c record.

again, this is all working properly in normal operation. the unit test just seems to stop as soon as the mock callout is returned, and does not complete the rest of the callOER method.

i could only test the mock response, but it seems like it would be much better to test the writeback as well.

fwiw, the big picture on the entire process is :

  • opportunity is marked as closed-won (stagename = acceptance with paperwork)
  • integration_bus__c record is created by process builder on opportunity, status__c = new
  • process on integration_bus__c record sets status__c to 'started' and uses invocable apex to enqueue the callout
  • queueable callout returns the exchange rate, and updates the exchange rate on the integration_bus__c record
  • process on integration_bus__c record updates a custom field exchange_rate__c on the opportunity
  • 1
    I suggest you to set debug logs to see what is actually executed and what is not in your unit test and check that after execution. Also, please use test.starttest and test.stopTest. That will ensure that your queueable method is executed and finished before asserts – kurunve Mar 8 '18 at 23:08
  • adding test.start / stop did the trick. i added test.stopTest(); right after update o and before the query on integration_bus__c - this allows all the async code to complete before the asserts. makes sense. thank you! – gorav Mar 9 '18 at 0:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.