Error: You have uncommitted work pending. Please commit or rollback before calling out.
Problem: I have a callout request which works only if I don't inserting an opportunity before it in test class.
In the following example I'm inserting an opportunity to reproduce the error, while actually not doing anything with the opportunity, in my real test I use the opportunity as a parent of an SObject I'm testing, and the VF controller is querying for fields of the opportunity parent, so if the opportunity is not inserted the controller won't be able to preform most of it logic, and test coverage will be low.
Small example as possible to reproduce the error:
@isTest
private class aaa_TestMockCallByPass {
@isTest static void test_mockCall_bypass()
{
Opportunity opp = new Opportunity(Name='testOpp', StageName='Close gagnée', CloseDate=Date.today());
// This does not work!
insert opp;
// This works - but it is a bad solution since the Id is relative to current salesforce org.
// Give opportunity a real Id from the system, and using upsert seems to work,
// meaning I have an opportunity to query from in the scope data of the test.
//opp.Id = '006L0000004WRDc';
//upsert opp;
Test.startTest();
//Set mock callout, to by pass test class limit, which prevent callout from test classes.
Test.setMock(HttpCalloutMock.class, new mockHttpResponseGenerator());
HttpRequest req = new HttpRequest();
req.setEndpoint('http://api.salesforce.com/foo/bar');
req.setMethod('GET');
Http h = new Http();
HttpResponse res = h.send(req);
Test.stopTest();
}
}
Note: that this error only happens when inserting Opportunity, I have tested insertion of other objects (Account, Contact, custom objects,...), and all works.
Test.startTest()...Test.stoptest()
- the mock is there to provide a fake response from the callout executed by whatever is being tested