I have a batch apex class that makes a callout at the beginning of each batch. I'm pretty certain that the callout error I'm getting isn't related to the order of DML statements and callouts within the method I'm testing.
However, the method I'm testing requires that there be certain SF records in place in the system for it to work. Therefore, in order to test the method, I need to 'generate' some test data within my test method. I figured if I put the code that creates and inserts records before the
test.startTest(); line, it wouldn't trigger the error about making callouts with work pending. Nope, still got the error!
So am I right about the reason for my error? If I start a TestMethod by inserting an account record, then fire up
test.startTest();, then execute the method that has a callout in it, will that give me an error? If so, how do I get around the error, since I need those records to exist before I run my method?
I should note that its not important that the records be inserted into the system in the same execution as the code i'm testing. The idea is that those records would already be there.
Edit in response to SFDCFox's answer:
Well, I still can't get it to work. I put all my test data generation methods (with the DML commands) before the
test.StartTest() block, then put my batchable code I was testing in the test block. Still got the
System.CalloutException: You have uncommitted work pending. Please commit or rollback before calling out error
Second Edit: the problem, clarified, and the solution I used
So by now I've confirmed that SF has a legitimate issue with testing callouts that are done within batch apex. Their documentation on the issue only covers tests that involve callouts made separate from batch apex.
Here's the basic outline of my test method:
- Create and insert an account record.
- Set the mock callout class, and in that process pass the inserted Account ID to the class so the callout's mock response can include the ID.
- Within the
test.StopTest(), I execute the batch apex, which contains the actual callout within its execute portion.
The error is due to inserting the account BEFORE making the callout. Using starttest()/stoptest() as suggested by SFDCfox doesn't seem to solve the issue, nor does the other linked solution on this thread that suggests testing the individual components of the batch process, rather than simply running a batchexecute. This is with the API # of all my classes updated to 30.0.
the solution I used
As linked in PJC's comment below. Essentially, rather than using the testMock class to create fake responses, I created an if clause within the batch apex itself where the callout was made. Before making the callout I check if the callout is being made during a test or not. If it's made during a test, rather than making the actual callout I simply assign the desired test response to the response variable.