+ Start a Discussion
bgm1234bgm1234 

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

Hi,


   I have batch apex with http call out. functinality working good. I need to run test case for that batch apex code coverage 100% but test case failed in following line
    "HTTPResponse res = http.send(con); " (con  refers to http request). and the error is
"You have uncommitted work pending. Please commit or rollback before calling out"

please can any one help me out from this issue..
Avidev9Avidev9
Well make sure you are running only one batch in your test class and enclose your code in Test.startTest() Test.stopTest()
bgm1234bgm1234
hi... thanks for  your response....
  i have tried what you said but no use..

please give me one more  idea.
CheyneCheyne
Have you read this post? http://salesforce.stackexchange.com/questions/17293/system-calloutexception-you-have-uncommitted-work-pending-please-commit-or-rol. It seems that it might address your issue. Are there any DML statements within your Test.startTest()/Test.stopTest() block? If so, try moving them outside of the block. 


bgm1234bgm1234
i have tried this but test fails 100% code covreage... help me ..out from this issue
CheyneCheyne
Is it failing due to an exception, or is it simply not providing enough code coverage? Could you post your complete code? I would would need to see both your batch apex code and test class in order to help you with code coverage. 
bgm1234bgm1234
@isTest
global class batchContactToMonitor_TC


    // ****** Adding Subscriber to Welcome List in Camapign Monitor ******************
   
   static testmethod void batchContact()
    {   
    Database.QueryLocator QL;
    Database.BatchableContext BC;
   
    set<string> emailofcontact = new set<string>();
    emailofcontact.add('test@test.com');
    List<CampaignMember > campaigns=new List<CampaignMember >();

   
        campaign cp1 = new campaign();
        cp1.name='testcampaign';
        cp1.status = 'sent';
        insert cp1;
       
        Contact contact = new Contact();
        contact.FirstName = 'Name';
        contact.LastName = 'ss';
        contact.email = 'testing12345@test.com';
        contact.Verify_Email_Address__c = 'testing12345@test.com';
        contact.Year1__c = '1990';
        contact.Month__c ='02';
        contact.Day__c = '12';
        contact.BirthDate = date.valueof('1990-05-16');
        contact.Date_of_Submission__c = date.valueof('1990-05-16')+1;
        contact.Street_Address_1__c  = 'addr1';
        contact.MAILINGCITY = 'High Point';
        contact.MailingPostalCode = '27265';
        contact.Feedback__c = 'true';
        contact.State__c = 'Alabama';
        contact.MAILINGSTATE = 'Alabama';
        contact.Cigarette__c  = True;
        contact.Use_Of_Cigarillos__c='test';
        contact.Cigarillos_frequency__c ='test';
        contact.Second_Preference_of_Cigarillos__c='test';
        contact.Second_Preference_other__c = 'test';
        contact.Purchase_Cigarillos__c = 'test';
        contact.Purchase_other__c = 'test';
        contact.Cigarillo_Preference__c = 'test';
        contact.Cigarillo_Flavor__c ='test';
        contact.Cigarillo_Flavor_other__c ='test';
        contact.Cigarette_Flavor__c='test';
        contact.Cigarette_Flavor_other__c ='test';
        contact.Gender__c = 'Male';
        contact.Feedback__c = 'Yes';
       
        system.debug('::::::::::::::::::::::'+cp1.id);
        contact.Campaign_ID__c = cp1.id;
        system.debug('>>>>>>>>>>>>>>>>'+contact.Campaign_ID__c );
        contact.Announcements__c= 'Yes';
        contact.Cigar_Flavor__c='test';
        contact.Cigar_Flavor_other__c='test';
        contact.Ciger_size__c='test';
        contact.Ciger_size_other__c ='test';
        contact.Eligibility__c = 'I am a smoker';
       
            
        insert contact;

       batchContactToMonitor bcontact=new batchContactToMonitor(emailofcontact);
       QL=bcontact.start(BC);
     
       Database.QueryLocatorIterator QIT =  QL.iterator();
         while (QIT.hasNext())
        {
          CampaignMember cm =(CampaignMember )QIT.next();
          cm.Contactid = contact.id;
          cm.CampaignId = cp1.id;

          insert cm;
      
          campaigns.add(cm);
        }
         bcontact.execute(bc,campaigns);
         bcontact.finish(BC);
        Test.startTest();
         Test.setMock(HttpCalloutMock.class, new TestBackgroundCheck());
        Test.stopTest();
       
       
        
      
    }
 
  
    } due to exception.
CheyneCheyne
You can't do a web service callout after a DML operation in the same transaction. You should move your batch execution to the inside of the Test.startTest block. Also, your batch class should be executed after you call to Test.setMock anyway, since this is where you define the response that your test http callouts will receive. 
bgm1234bgm1234
have u said like this.... i tried but no use



@isTest
global class batchContactToMonitor_TC


    // ****** Adding Subscriber to Welcome List in Camapign Monitor ******************
   
   static testmethod void batchContact()
    {   
    Database.QueryLocator QL;
    Database.BatchableContext BC;
   
    set<string> emailofcontact = new set<string>();
    emailofcontact.add('test@test.com');
    List<CampaignMember > campaigns=new List<CampaignMember >();
    batchContactToMonitor bcontact=new batchContactToMonitor(emailofcontact);
    QL=bcontact.start(BC);
    Test.startTest ();
    test.setMock(HttpCalloutMock.class, new TestBackgroundCheckForBulk());
    bcontact.execute(bc,campaigns);
    Test.stopTest();
   
    campaign cp1 = new campaign();
    cp1.name='testcampaign';
    cp1.status = 'sent';
    insert cp1;
       
    Contact contact = new Contact();
    contact.FirstName = 'Name';
    contact.LastName = 'ss';
    contact.email = 'testing12345@test.com';
    contact.Verify_Email_Address__c = 'testing12345@test.com';
    contact.Year1__c = '1990';
    contact.Month__c ='02';
    contact.Day__c = '12';
    contact.BirthDate = date.valueof('1990-05-16');
    contact.Date_of_Submission__c = date.valueof('1990-05-16')+1;
    contact.Street_Address_1__c  = 'addr1';
    contact.MAILINGCITY = 'High Point';
    contact.MailingPostalCode = '27265';
    contact.Feedback__c = 'true';
    contact.State__c = 'Alabama';
    contact.MAILINGSTATE = 'Alabama';
    contact.Cigarette__c  = True;
    contact.Use_Of_Cigarillos__c='test';
    contact.Cigarillos_frequency__c ='test';
    contact.Second_Preference_of_Cigarillos__c='test';
    contact.Second_Preference_other__c = 'test';
    contact.Purchase_Cigarillos__c = 'test';
    contact.Purchase_other__c = 'test';
    contact.Cigarillo_Preference__c = 'test';
    contact.Cigarillo_Flavor__c ='test';
    contact.Cigarillo_Flavor_other__c ='test';
    contact.Cigarette_Flavor__c='test';
    contact.Cigarette_Flavor_other__c ='test';
    contact.Gender__c = 'Male';
    contact.Feedback__c = 'Yes';
    contact.Campaign_ID__c = cp1.id;
    contact.Announcements__c= 'Yes';
    contact.Cigar_Flavor__c='test';
    contact.Cigar_Flavor_other__c='test';
    contact.Ciger_size__c='test';
    contact.Ciger_size_other__c ='test';
    contact.Eligibility__c = 'I am a smoker';
              
    insert contact;

   
    bcontact.finish(BC);
       
    }
 
}
CheyneCheyne
That looks better, but I would move the Test.startTest method to the end of the procedure, as you had it before, so that the contact records exist when you execute the batch.


bgm1234bgm1234
i have moved to the end test.stoptest to the end . no use
CheyneCheyne
It still says "You have uncommitted work pending"?
bgm1234bgm1234
yes....
priyanshu nemapriyanshu nema
Hi,
yes Cheyne is right, Just call DML and webservice class in different transaction. I mean call batch class after Test.stopTest() because your batch class should be executed after you call to Test.setMock() since this is where you define the response that your test http callouts will receive.
   Like this: - 
   Test.startTest ();
    test.setMock(HttpCalloutMock.class, new TestBackgroundCheckForBulk());
    Test.stopTest();
    bcontact.execute(bc,campaigns); 

It is working for me.
Célio XavierCélio Xavier
I was getting the same error, however, I decided to update the account before the callout, as I needed to concatenate some values, I followed this strategy, below is a simple example:
public static void updateAccount(Id recordId, String City, String PostalCode, String Country, String Street, String State_Province, String AddressType, String Complement, String Neighborhood, String Number_Address){
		
        String Number_Address_nm = Number_Address.replaceAll('[^0-9]', '');
        String PostalCode_nm = PostalCode.replaceAll('[^0-9]', '');
        String acId = [SELECT Id FROM Account WHERE Id =: recordId LIMIT 1].Id;  
        
        Account ct = new Account();
        ct.Id = acId;
        ct.BillingCity = City;
        ct.BillingCountry = Country;
        ct.BillingPostalCode = PostalCode_nm;
        ct.BillingState = State_Province;
        ct.BillingStreet = AddressType + ' ' + Street + '   Nº: ' + Number_Address_nm + '  ' + Complement + '   BAIRRO: ' + Neighborhood ;
        update ct;      
    }
    
    @future(callout=true)
    public static void Call_API(Id recordId, String City, String PostalCode, String Country, String Street, String State_Province, String AddressType, String Complement, String Neighborhood, String Number_Address){        

            ChangeAddressAPI.CallChangeAddressAPI(recordId, City, PostalCode, Country, Street, State_Province, AddressType, Complement, Neighborhood, Number_Address); 

    }
}