I'm trying to write test code for a Batchable
class that AllowsCallouts
. I've written a lot of other test code that uses HttpCalloutMock
classes, and planned to do so for this class as well.
And, per best practices, I'm setting up my test data before calling Test.startTest()
. Even so, I get a CalloutException:
System.CalloutException: You have uncommitted work pending. Please commit or rollback before calling out
This somewhat makes sense, because my start()
method passes a SOQL query to Database.getQueryLocator()
and my execute()
method makes the web callouts. I'm guessing that when my test method calls test.stopTest()
, both start()
and execute()
run in the same context. In regular batch operation, they happen in separate contexts so there isn't any uncommitted work.
I intend to work around this by calling the methods directly, possibly even calling start()
before Test.startTest()
, and then using the returned Database.QueryLocator
to get the list of records I'll pass into execute()
.
I don't like the fact that I'm not testing the batch size used by the static method that kicks off the batch with Database.executeBatch()
, so I'll probably have that use a constant that I can reference from my test code to ensure it's using the same batch size.
Salesforce kind of addresses this in the "Asynchronous Apex and Mock Callouts" section of the Summer '13 Release Notes, but they don't make reference to Batchable classes with Callouts. They only talk about making callouts and testing Batchable classes in the same test method.
So, my question is whether there is a better way to write this test. I'm also throwing this out so others searching the site can learn about possible workarounds.