0

I'm facing

"System.CalloutException: You have uncommitted work pending. Please commit or rollback before calling out"

Here is my codes: (Adding only the relevant code)

Callout Class which contains the response logic (getAWBResponse method):

global class FreightAWBPopUpController {

    // Aura enabled instance variables here

    @AuraEnabled
    public static FreightAWBPopUpController getRecordUpdate(Id CaseId)
    {

        string requestJson;
        FreightAWBPopUpController obj = new FreightAWBPopUpController();
        list<Freight_AWBResponseParsing.LatestStatus> lsList = new list<Freight_AWBResponseParsing.LatestStatus>();

        // getting case record values and custom settings here
        Case caseRecord     = [SELECT Id, CaseNumber FROM Case WHERE Id =: CaseId];
        Integration_User_Tradesite__c freightIcargoUserDetails = Integration_User_Tradesite__c.getValues('Freight_iCargo_Integration');        

        // Checking availability of AWB Number, accordingly requesting 
        if(String.isNotBlank(caseRecord.Freight_AWB_Number__c)){
            requestJson = getRequestString(freightIcargoUserDetails.Username__c, freightIcargoUserDetails.Password__c, caseRecord.Freight_AWB_Number__c);
        }
        else{
            // show error AWB Number not provided. Lightning work to be done
            return obj;
        }
        system.debug(' @@ j2Apex.sample string @@ ' + requestJson);

        try{
            Boolean responseSuccess;
            HttpResponse res = getAWBResponse(requestJson, freightIcargoUserDetails);

            if(res.getStatusCode() == 200){
                responseSuccess = true;
            }
            else if(res.getStatusCode() == 400){
                res = getAWBResponse(requestJson, freightIcargoUserDetails);
                if(res.getStatusCode() == 200)
                    responseSuccess = true;
                else if(res.getStatusCode() == 400)
                    responseSuccess = false;
            }

            if(responseSuccess)
            {
                Freight_AWBResponseParsing awbResponseParsed = Freight_AWBResponseParsing.parse(res.getBody());        
                lsList = awbResponseParsed.ShipmentMilestones.shipmentsTracked.history;
                obj.LatestStatusString = JSON.serialize(lsList);
                system.debug(' @@ Latest Status List @@ ' + obj.LatestStatusString);

                caseRecord = returnParsedCase(res.getBody(), caseRecord);
                caseRecord.Latest_Status__c = system.now();
                update caseRecord;

                return obj;
            }
            else{
                // error message for false
                return obj;
            }
            return null;
        }
        catch (JSONException jsonExcep){
            return obj;
        }
    }

    public static HTTPResponse getAWBResponse(string requestJson, Integration_User_Tradesite__c freightIcargoUserDetails){

        String username     = freightIcargoUserDetails.UserName__c;             
        String password     = freightIcargoUserDetails.Password__c; 
        string endPoint     = freightIcargoUserDetails.Endpoint__c; 
        string method       = 'POST';

        String accessToken;
        accessToken = Freight_AuthenticateAPIGateWay.returnAccessToken();

        HttpRequest req     = new HttpRequest();
        req.setEndpoint(endPoint);
        req.setMethod(method);
        req.setBody(requestJson);
        req.setHeader('Authorization','Bearer ' + accessToken);
        req.setHeader('Content-Type','application/json');
        req.setHeader('accept','application/json');
        Http http           = new Http();
        HTTPResponse res    = new HTTPResponse();

        //if(!Test.isRunningTest()){
            res    = http.send(req);
            return res;
        //}

        return null;        

    }

    public static Case returnParsedCase(string jsonResponse, Case caseRecord){

        // some logic here
        return caseRecord;
    } 

    public static string getRequestString(string userName, string Password, string awbNumber){

        Freight_AWBRequestJson awbRequestJson                       = new Freight_AWBRequestJson();
        awbRequestJson.Shipments                                    = new Freight_AWBRequestJson.Shipments();

        // some logic here
        return awbRequestJson.convertToJsonString(awbRequestJson);

    }    

}

HttpCalloutMock Class:

@isTest
public class Freight_AWBMockRequest implements HttpCalloutMock{

    protected String sampleJSON;
    protected Integration_User_Tradesite__c iut;

    public Freight_AWBMockRequest(String sampleJSON , Integration_User_Tradesite__c iut){
        this.sampleJSON = sampleJSON;
        this.iut = iut;
    }

    public HttpResponse respond(HTTPRequest req)
    {
        HttpResponse res = FreightAWBPopUpController.getAWBResponse(sampleJSON,iut);
        System.assertEquals('POST', req.getMethod());
        return res;
    }
}

Test Class :

@isTest
public class FreightAWBPopUpControllerTest {

    @isTest 
    static void AWBtileTest() {

        String caseRTId = Schema.SObjectType.Case.getRecordTypeInfosByName().get('Freight Claims').getRecordTypeId();
        String accRTId = Schema.SObjectType.Account.getRecordTypeInfosByName().get('Freight Account').getRecordTypeId();

        // adding some dummy custom setting values
        Integration_User_Tradesite__c ss = new Integration_User_Tradesite__c(
                                            Name = 'Freight_iCargo_Integration',
                                            Username__c = 'abcd',
                                            Password__c = 'abcdee',
                                            Endpoint__c = 'https://test.com/sample',
                                            );
        insert ss;

        String sampleJSON;
        HTTPResponse resp;

        // insert account - testacc
        // insert contact - testcon

        Case awbNumOn = new Case(AccountId = testacc.id,
                                 ContactId = testcon.id,
                                 RecordTypeId = caseRTId,
                                 Subject = 'the case',
                                 Freight_AWB_Number__c = '081-27182256'
                                );
        insert awbNumOn;

        sampleJSON = FreightAWBPopUpController.getRequestString(ss.Username__c,ss.Password__c,awbNumOn.Freight_AWB_Number__c);

        Test.setMock(HttpCalloutMock.class, new Freight_AWBMockRequest(sampleJSON,ss));
        resp = FreightAWBPopUpController.getAWBResponse(sampleJSON,ss);
        FreightAWBPopUpController.returnParsedCase(resp.getbody(),awbNumOn);

        Test.StartTest();
            FreightAWBPopUpController.getRecordUpdate(awbNumOn.Id);
        Test.StopTest();    

    }

}
2

The dreaded "uncommited work" exception! For any given transaction, ALL of the Callouts have to happen before ANY of the DML.

Looks like your test Class does an insert awbNomOn; followed by a FreightAWBPopUpController.getAWBResponse(sampleJSON,ss); within the same transaction context. That's what's throwing the exception.

You can move the FreightAWBPopUpController.getAWBResponse(sampleJSON,ss); so that it's between the test.startTest(); ... test.stopTest(); statements. You can also do your DML insert awbNomOn; into an @testSetup decorated method (which is what I recommend).

Either of those should prevent the exception in your test Class.

Just have to remember, for any given transaction, ALL of the Callouts have to happen before ANY of the DML. By the way, I learned that enqueueing a job is (unfortunately) ALSO considered "pending work"

  • I used a test Utility class to insert the records and invoked the methods inside my base test class. I still faced errors. Only @testSetup i had to use to resolve this issue. Thanks for your help. I fixed the code. – AjaySFDC Sep 2 '17 at 19:32

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.