+ Start a Discussion
AaranAaran 

Error:You have uncommitted work pending. Please commit or rollback before calling out

Hi,

 

I'm getting 'You have uncommitted work pending. Please commit or rollback before calling out' msg when I run my test class.  Can somebody help me to fix this please?

 

global class LeadCallOutBatchable implements Database.Batchable<sObject>, Database.AllowsCallouts{

global final String Query;

   global final String Entity;

 

   global LeadCallOutBatchable() {

      Query='SELECT Id, FirstName, LastName, UserName__c, Email, Title, fs_skills__c, fs_overview__c, fs_facebook__c, fs_twitter__c, fs_linkedin__c ' +   'FROM Lead WHERE UserName__c != null';  

        Entity= 'Lead';

   }

 

   global Database.QueryLocator start(Database.BatchableContext BC) {

      return Database.getQueryLocator(query);

   }

    

   global void execute(Database.BatchableContext BC, List<Lead> scope) {

        

        List<Lead> leadsToUpdate = new List<Lead>();

        String PersonURL ;

        Integer count = 0;

        System.debug('scope: ' + scope);

        

        for(Lead leadRec : scope ) {   

            String jResponse = '';

            JPersonList deserialPersonList = new JPersonList();

            count++;

            System.debug('Count: ' + count);           

            PersonURL =  URL

            

            try {

                HttpRequest req = new HttpRequest();

                req.setMethod('GET');

                String username = JUSERNAME;

                String password = JPW;

                Blob headerValue = Blob.valueOf(username + ':' + password);

                String authorizationHeader = 'Basic ' + EncodingUtil.base64Encode(headerValue);

                req.setHeader('Authorization', authorizationHeader);

                req.setHeader('Accept', 'application/json');

                req.setEndPoint(PersonURL);

                

                Http http = new Http();

                system.debug('req: ' + req);

                HTTPResponse res = http.send(req);

         

               jResponse = res.getBody();

                

 

                jResponse = jResponse.Replace('throw \'allowIllegalResourceCall is false.\';', '');    

                //System.debug('Request Body: ' + jResponse);

                

                JSONParser parser = JSON.createParser(jResponse);

 

  // deserialize

                JObject personRecord = (JObject) System.JSON.deserialize(jResponse, JObject.class);

 

//some codes to compare

                

                       leadsToUpdate.add(leadRec);

                       System.debug('leadsToUpdate: ' + leadsToUpdate);

            }

            }

            catch(Exception ex) {

                System.debug('Exception: ' + ex);   

            }

        }

        System.debug('leadsToUpdate: ' + leadsToUpdate);

        update leadsToUpdate;

    }

        

   global void finish(Database.BatchableContext BC){ 

   }

}

 

 

test classes:

 

@isTest

public class LeadCalloutBatchableTest{

    public static testmethod void TestLeadCalloutBatchable() {

        

        List<ID> acRecs=new List<ID>();

        Lead testLead = new Lead( IncludeInSFToSync__c = true, FirstName = 'STEVE' , LastName = 'JOHN', UserName__c = 'stevej', Email = 'r@gmail.com', Title = 'testtest', fs_skills__c = 'developement' , fs_overview__c='good', fs_facebook__c='facebook', fs_twitter__c='twitter', fs_linkedin__c = 'linkedin');

        insert testLead;

        acRecs.add(testLead.id);

       

        string JSONstr = 

        SingleRequestMock fakeResponse = new SingleRequestMock(200,'Complete', JSONstr ,null);

 

        Test.startTest();

        Test.setMock(HttpCalloutMock.class, fakeResponse);

        Database.executeBatch(new LeadCallOutBatchable(), 200);

       

        Test.stopTest();

   

    }

}

 

 

@isTest

global class SingleRequestMock implements HttpCalloutMock {

    protected Integer code;

    protected String status;

    protected String bodyAsString;

    protected Blob bodyAsBlob;

    protected Map<String, String> responseHeaders;

  

   

    public SingleRequestMock(Integer code, String status, String body, Map<String, String> responseHeaders) {

        this.code = code;

        this.status = status;

        this.bodyAsString = body;

        this.bodyAsBlob = null;

        this.responseHeaders = responseHeaders;

 

    }

         

   public SingleRequestMock(Integer code, String status, Blob body, Map<String, String> responseHeaders) {

        this.code = code;

        this.status = status;

        this.bodyAsBlob = body;

        this.bodyAsString = null;

        this.responseHeaders = responseHeaders;

    }

    

    public HTTPResponse respond(HTTPRequest req) {

        HttpResponse resp = new HttpResponse();

        resp.setStatusCode(code);

        resp.setStatus(status);

        if (bodyAsBlob != null) {

            resp.setBodyAsBlob(bodyAsBlob);

        } else {

            resp.setBody(bodyAsString);

        }

        

        if (responseHeaders != null) {

            for (String key : responseHeaders.keySet()) {

                resp.setHeader(key, responseHeaders.get(key));

            }

        }

        return resp;

    }  

}

 

 

 

Dhaval PanchalDhaval Panchal

I have also faced same issue. When we call DML operation (i.e. insert/update/upsert) and then we make callout then this issue is occures. Do one thing do not make any DML operation before making callout.

Maf_007Maf_007

Hi, 

 

Use MockCallOut Class for testing web service. And create another test method which skips the the callout when you test is running. That should give you enough coverage. and should not give you error too.

AaranAaran

Thanks for your reply Dhaval.  I've tried that way, but didn't work. I need to do DML operation before making callout in order to use the dml value to make callout .  I'm new to salesforce and pls let me know how to fix this.

 

Thank you

 

 

AaranAaran

Thanks for the reply Maf_007.  I am new to salesforce and could you please show me how to write the test method which skips the callout?  

 

Thank you

Maf_007Maf_007
global class LeadCallOutBatchable implements Database.Batchable<sObject>, Database.AllowsCallouts{
global final String Query;
   global final String Entity;
 
   global LeadCallOutBatchable() {
      Query='SELECT Id, FirstName, LastName, UserName__c, Email, Title, fs_skills__c, fs_overview__c, fs_facebook__c, fs_twitter__c, fs_linkedin__c ' +   'FROM Lead WHERE UserName__c != null';  
        Entity= 'Lead';
   }
 
   global Database.QueryLocator start(Database.BatchableContext BC) {
      return Database.getQueryLocator(query);
   }
    
   global void execute(Database.BatchableContext BC, List<Lead> scope) {
        
        List<Lead> leadsToUpdate = new List<Lead>();
        String PersonURL ;
        Integer count = 0;
        System.debug('scope: ' + scope);
        
        for(Lead leadRec : scope ) {   
            String jResponse = '';
            JPersonList deserialPersonList = new JPersonList();
            count++;
            System.debug('Count: ' + count);           
            PersonURL =  URL
            
            try {
                HttpRequest req = new HttpRequest();
                req.setMethod('GET');
                String username = JUSERNAME;
                String password = JPW;
                Blob headerValue = Blob.valueOf(username + ':' + password);
                String authorizationHeader = 'Basic ' + EncodingUtil.base64Encode(headerValue);
                req.setHeader('Authorization', authorizationHeader);
                req.setHeader('Accept', 'application/json');
                req.setEndPoint(PersonURL);
                
                Http http = new Http();
                system.debug('req: ' + req);
             if (Test.isRunningTest()) { //ADD THIS BLOCK PLEASE
                HTTPResponse res = http.send(req);
             }
         
               jResponse = res.getBody();
                
 
                jResponse = jResponse.Replace('throw \'allowIllegalResourceCall is false.\';', '');    
                //System.debug('Request Body: ' + jResponse);
                
                JSONParser parser = JSON.createParser(jResponse);
 
  // deserialize
                JObject personRecord = (JObject) System.JSON.deserialize(jResponse, JObject.class);
 
//some codes to compare
                
                       leadsToUpdate.add(leadRec);
                       System.debug('leadsToUpdate: ' + leadsToUpdate);
            }
            }
            catch(Exception ex) {
                System.debug('Exception: ' + ex);   
            }
        }
        System.debug('leadsToUpdate: ' + leadsToUpdate);
        update leadsToUpdate;
    }
        
   global void finish(Database.BatchableContext BC){ 
   }
}
 
 
test classes:
 
@isTest
public class LeadCalloutBatchableTest{
    public static testmethod void TestLeadCalloutBatchable() {
        
        List<ID> acRecs=new List<ID>();
        Lead testLead = new Lead( IncludeInSFToSync__c = true, FirstName = 'STEVE' , LastName = 'JOHN', UserName__c = 'stevej', Email = 'r@gmail.com', Title = 'testtest', fs_skills__c = 'developement' , fs_overview__c='good', fs_facebook__c='facebook', fs_twitter__c='twitter', fs_linkedin__c = 'linkedin');
        insert testLead;
        acRecs.add(testLead.id);
       
        string JSONstr = 
        SingleRequestMock fakeResponse = new SingleRequestMock(200,'Complete', JSONstr ,null);
 
        Test.startTest();
        Test.setMock(HttpCalloutMock.class, fakeResponse);
        Database.executeBatch(new LeadCallOutBatchable(), 200);
       
        Test.stopTest();
   
    }
}
 
 
@isTest
global class SingleRequestMock implements HttpCalloutMock {
    protected Integer code;
    protected String status;
    protected String bodyAsString;
    protected Blob bodyAsBlob;
    protected Map<String, String> responseHeaders;
  
   
    public SingleRequestMock(Integer code, String status, String body, Map<String, String> responseHeaders) {
        this.code = code;
        this.status = status;
        this.bodyAsString = body;
        this.bodyAsBlob = null;
        this.responseHeaders = responseHeaders;
 
    }
         
   public SingleRequestMock(Integer code, String status, Blob body, Map<String, String> responseHeaders) {
        this.code = code;
        this.status = status;
        this.bodyAsBlob = body;
        this.bodyAsString = null;
        this.responseHeaders = responseHeaders;
    }
    
    public HTTPResponse respond(HTTPRequest req) {
        HttpResponse resp = new HttpResponse();
        resp.setStatusCode(code);
        resp.setStatus(status);
        if (bodyAsBlob != null) {
            resp.setBodyAsBlob(bodyAsBlob);
        } else {
            resp.setBody(bodyAsString);
        }
        
        if (responseHeaders != null) {
            for (String key : responseHeaders.keySet()) {
                resp.setHeader(key, responseHeaders.get(key));
            }
        }
        return resp;
    }  
}

 

Could you please add the block I added in your code and see what happens??

AaranAaran

Hi Maf,

 

Still not working. I need to fix this soon.. pls help me....

 

Thanks,