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

So I have a method that takes as a parameter an Id of a object and uses it to make an external callout. Unfortunately I can’t seem to figure out any way to test it.

@isTest static void sometimes_salesforces_sucks() {
   My_Object__c foo = new My_Object__c(Name='test');
   insert foo;
   MyClient client = new MyClient();
   MyMockResponseGenerator mockResponse = new MyMockResponseGenerator();
   Test.setMock(HttpCalloutMock.class,mockResponse);

   Test.startTest();
   client.bar(foo.Id);
   Test.stopTest();
}

This question says that using start/stop test should work, but it doesn’t work for me

Answer

You can’t do a web service callout after a DML operation in the same transaction.
try this code:-

@isTest static void sometimes_salesforces_sucks() {
   My_Object__c foo = new My_Object__c(Name='test');
   insert foo;
   MyClient client = new MyClient();
   Test.startTest();
   Test.setMock(HttpCalloutMock.class,new MyMockResponseGenerator());
   client.bar(foo.Id);
   Test.stopTest();
}

You cannot perform a DML operation prior to a callout. All the DML operations should be invoked only after you are done with callouts.So, make a webservice callout first and then save the request.

If you are making multiple callouts, then save all the requests in a list or map and post callouts you save them.

Basically the following scenario will work :-

query
callout
query
callout
insert

callout
callout
callout
insert or update

But the following scenario will fail :-

callout
insert
callout <—- fails=”” here=”” p=””>
Possible workaround :-

splits the transaction into two separate Ajax processes. The first inserts the record and the second performs the callout and is able to update the newly inserted record.

Attribution
Source : Link , Question Author : NSjonas , Answer Author : Ajay Dubedi

Leave a Comment