1

I'm trying test a critical part of an application that is in a batch process and makes callouts to a server.

    MyObject__c obj = new MyObject__c(name='test');
    insert obj;

    Test.startTest();
    Test.setMock(WebServiceMock.class, new MyWebServiceMock());
    //run the batch process
    MyBatchProcess.createBatch(obj);
    Test.stopTest();

When I attempt to "mock" the callout, I get hit with this bug:

System.CalloutException: You have uncommitted work pending. Please commit or rollback before calling out

According to the docs on testing callouts, this shouldn't happen.

Dug into it a bit more and found this article where someone opened a case. Salesforce apperently responded by saying to "use the isTestRunning() method to avoid the callout".

This is obviously not ideal, as It makes it very hard to do any useful assertions. The only work around I can think of is to overload the batch constructor and pass my test inputs in. I would really like to avoid this if possible.

Anyone got a solution?

6
  • Could it be that you're hitting this error in a deploy? As for some reason salesforce checks the "don't do DML before callouts"-limit once during a deploy, so if you have a completely separate test running before your callout test, and it's doing a DML. Then you could run into this problem, take a look at: salesforce.stackexchange.com/questions/11606/…
    – pjcarly
    Commented Dec 9, 2014 at 8:30
  • Doesn't seem to matter how I run the test. I've been running using mavens-mate synchronous test runner, but I can also run using the async test and I get the same results. Only running the single test so order shouldn't matter.
    – NSjonas
    Commented Dec 9, 2014 at 9:08
  • 1
    Somehow you're doing a DML statement before the callout, perhaps a Database.setSavepoint(); which is often overlooked, but also consumes a DML.
    – pjcarly
    Commented Dec 9, 2014 at 12:18
  • Ahhh, your right. My function equivalent to MyBatchProcess.createBatch(obj); does preform some updates on OBJ. I completely overlooked that aspect. Any explanation on why it works in the real world, but not in a unit test? I guess I need to refactor these into two different functions if I want to test.
    – NSjonas
    Commented Dec 9, 2014 at 16:59
  • Also, if you submit an answer, I will give you the check
    – NSjonas
    Commented Dec 9, 2014 at 16:59

1 Answer 1

2

I have never gotten Batch and Callouts to work in tests - see here for more detail

My approach these days is to put the all the code from the batch in a regular class that operates as the Batch Handling Class with its own Start, Execute and Finish. That way, I can call the code with callouts directly in my tests and it will work fine. The batch uses that class, but then I can use Test.IsRunningTest() to avoid calling those methods in the test context. Not perfect by any means, but it is the easiest way to get batches, callouts and tests to play nicely...

3
  • Show how do you test different outputs from the callout inside of isTestRunning()? For a simplified example, what if my callout returns a status code and I do different things depending on its code (0,1,2,3 etc). How do you test each of those logical branches?
    – NSjonas
    Commented Dec 9, 2014 at 17:51
  • ohhh i think i got it.... The class could have a method that handles the status code returned by the callout. The callout itself would be made in the batch process with isTestRunning() and then pass the result into the class handler method. That way, you can test the class independent of the callout.
    – NSjonas
    Commented Dec 9, 2014 at 17:54
  • I let the handling class do everything - I just pass the scope variable to the handling class if I am not running a test....if you have an instance of the handling class (rather than calling a static method), you can then set variables in the handling class and retrieve those variables when you return to the batch if you are keeping a track of each execution for the final piece etc... Commented Dec 10, 2014 at 0:10

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .