The Good Word on Unit Tests, HTTP Callouts, and Creating Test Data

So you want to mix dml inserts and make callouts in your tests? That’s Cray Cray!

Here’s the low down on how to get around the “You have uncommitted changes pending please commit or rollback…” when trying to mix DML and HTTP Callouts in your test methods.

First, a little background (and a health and safety warning)
Sooner or later you’ll be faced with testing a method that both a.) manipulates existing data, and b.) calls out to a third party service for more information via HTTP.  Sadly, this is one of those situations where testing the solution is harder than the actual solution. In a testing situation, you *should* be inserting the data that your method is going to rely on. But making a DML call — insert — will prevent any further HTTP callouts from executing within that Apex context.

Yuck. That means inserting say, an account, and then making a call out with some of that data … well that just won’t work. No Callouts after a DML call.

So lets cheat a bit
Apex gives us two tools that are helpful here. The first is the @future annotation. Using the @future annotation and methodology allows you to essentially switch apex contexts, at the cost of synchronous code execution. Because of the Apex context switch governor limits, DML flags are reset.

Our second tool is a two-fer of Test.startTest() and Test.stopTest(). (you are using Test.startTest() and Test.StopTest() right?) Among their many tricks is this gem: When you call Test.stopTest(); all @future methods are *immediately* executed. When combined together, these two tricks give us a way to both insert new data as part of our test, then make callouts (which we’re mocking of course) to test; for example, that our callout code is properly generating payload information etc. Here’s an example:

This works, because we can both a.) switch to an Apex context that’s not blocked from making HTTP Callouts, and b.) force that asynchronous Apex context to execute at a given time with test.stopTest().

Have further questions about Unit Tests, HTTP Callouts, and Creating Test Data? Reach out to us! Leave your questions below, or click here to submit them via email. 

Stay up to date with the latest in Salesforce insights by signing up for our Salesforce newsletter. Click here to subscribe.

Phone: 312-602-4000
222 W. Adams
Chicago, IL 60606
Show Buttons
Share On Facebook
Share On Twitter
Share on LinkedIn
Hide Buttons