20

I have a number of test methods that call Test.setMock(WebServiceMock.class, new SomeWebServiceMockImpl()); where SomeWebServiceMockImpl implements WebServiceMock.

These test methods pass when I run the tests via:

  • Setup > App Setup > Develop > Apex Test Execution.
  • Setup > App Setup > Develop > Apex Classes > class name > Run Tests.
  • Eclipse > Run Tests
  • the Developer Console Tests tab

However, when I try and create a managed package that includes these tests they fail with the message:

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

I understand that this message usually appears after performing DML inserts/updates - see Testing HttpCallout with HttpCalloutMock and UnitTest Created Data. As such, I've been careful in these test methods not to make any database calls.

Why are these tests failing during the managed package creation but otherwise passing?

I remember reading about this recently but can't recall where. I suspect it is a known issue. I thought the work around was to execute the Mock tests first, so I moved them all to the top of the class and prefixed them with 'aaa_'. This didn't resolve the issue.

2 Answers 2

13

From the same thread as Daniel Ballinger's answer, BBeaird points out that wrapping the mock callouts in Test.startTest() and Test.stopTest() also works around the bug.

4
  • 1
    I would say this is really the recommended path. It actually kind of makes sense - using the mock interface simply puts it in the same context as waiting on a future call, scheduled task, etc.
    – joshbirk
    Commented Mar 4, 2013 at 17:46
  • 4
    doesn't seem to work for me
    – NSjonas
    Commented Aug 8, 2014 at 21:30
  • Thank you so much! I was completely stuck this morning. My code was working without the start/stop test last week so I was baffled when it stopped working this morning. Your post here really made a difference! I implemented it and it was the solution!
    – muchavie
    Commented Jul 8, 2020 at 14:39
  • I found that this didn't work for me until I created my test data using @testSetup. This presumably creates it in a different execution context so the mock callout isn't running after a DML operation in its own execution context.
    – lemming
    Commented Jul 9, 2021 at 14:17
12

I found the post that mentioned this issue and the work around solution.

Testing Webservice Callouts with Winter '13 Test.setMock fails because of Test Data creation.

colemab:

... this appears to be a known issue in the deployment tool for Winter 13. Basically the deployment tool isn't running each class as an individual run during predeployment testing and so this error will popup for new classes with call outs that run after test classes that do any DML. Which is just about every class right?

Please note that since the deploy tests are different than the run all tests (for unknown reasons), you will never see this kind of error until you deploy to production.

Since the tests on deployment run in alpha order, the workaround from support was to take my new class and name it very high alpha sort like 'aaa' so that it could run before any DML in other classes.

Support didn't provide a ETA for a fix and didn't say if this would be listed on the official known issues list.

So I created a new class with "aaa_" at the start of the classname and added only the test cases using Test.setMock to it. I can now create the managed package with the tests otherwise unchanged.

2
  • 1
    Wow, that's pretty crazy, and would have been very hard to troubleshoot without internal SFDC knowledge.
    – Mikey
    Commented Nov 13, 2012 at 1:11
  • @Mikey I think I was lucky that I had stumbled past that post recently and vaguely recalled it. Certainly an unexpected feature/gotcha in the HTTP callout functionality. Commented Nov 13, 2012 at 1:42

You must log in to answer this question.

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