I Identified the issue in Batch Class code. There was a DML operation between callouts which was causing this.
Thanks for your help @Eric.
believe since you are implementing database.stateful that the DML
persits and thus you cannot make a callout in the finish method
Database.stateful is to persist values of instance variables and not for DML operations. Issue was in Finish method code, while doing 4 difffenent APEX callouts code was inserting records(DML) inbetween callouts. I just moved all the DML statements after callouts to resolve the issue.
A quick search may have found the answer, but it is really simple:
Wrap the mock in a test.startTest();
test.startTest();
Test.setMock(HttpCalloutMock.class, new CalloutMock());
update opp; // this update makes callout
test.stoptest();
the reason is just like in a non-test environment. You cannot make a callout after doing any dml. Since you are creating a User, you cannot do a callout after in the same transaction. the test.StartTest() provides a new context for the callout to be run in as well as a new set of governor limits....
NOTE
Not sure why you have a batch code there, but if you are executing a batch from a trigger (potentially a problem) you will have to:
Call the start, execute, finish methods separately as it is a know issues that you will get this error regardless of the test.startTest if the callout is from a batch
If that is the case, unfortunatly you will have to wrap that part of your trigger that calls the batch in a :
if(!test.isRunningTest())
and change your test method to:
test.startTest();
Test.setMock(HttpCalloutMock.class, new CalloutMock());
update opp; // this update makes callout
//call your start method
[batch].execute(null,New sObject[]{opp});
//call your finish method
test.stoptest();
You can also just wrap the callout in the batch to prevent it from running during a test except when a static property is set. that way your trigger is unaltered and the batch / test controls when the callout is made during a test method
i.e in the batch.
public static testCallout = false;
.....
if( (testCallout && test.isRunningTest()) || !test.isRunningTest())
//make callout
then set the testCallout = true
from your test class
this leaves your trigger unaltered
You can find many topics on this issue by searching for "You have uncommitted work pending batch test" on this site
Best Answer
Problem
Actually, webservice or http callouts and a DML won't take place in the same transaction. And that's why you are getting the error. Read about this problem.
Solution
@Future
annotation. I had such problem and resolved using that.Code Sameple This is just a out-of-mind code. but you need make changes or test this as per your need.