Skip to main content

SF-9204 · Concept · Medium

What does Test.setMock() do?

✓ Verified by Vikas Singhal · Last reviewed 5/17/2026 · Updated for Spring '26

Test.setMock() is the static method you call inside a test to replace the HTTP or SOAP transport layer with a mock. Once registered, every callout from your production code is intercepted and answered by the mock, with no real network traffic.

The signature

Test.setMock(Type interfaceType, Object instance)
  • interfaceType — either HttpCalloutMock.class or WebServiceMock.class
  • instance — an instance of a class that implements the chosen interface

Why it exists

Apex tests run with callouts disabled by default. Try to call Http.send() in a test without setting up a mock and you’ll get:

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

Or, more specifically, the platform refuses to make real HTTP requests from test code so that:

  • Tests don’t depend on external services being up
  • Tests don’t make real API calls (charges, side effects, rate limits)
  • Tests run deterministically — same result every time

Test.setMock() is the platform’s official escape hatch.

Minimal example

@isTest
public class WeatherMock implements HttpCalloutMock {
    public HttpResponse respond(HttpRequest req) {
        HttpResponse res = new HttpResponse();
        res.setBody('{"temp_c": 22.5}');
        res.setStatusCode(200);
        return res;
    }
}

@isTest
static void getTempC_returnsParsedValue() {
    Test.setMock(HttpCalloutMock.class, new WeatherMock());

    Test.startTest();
    Decimal t = WeatherService.getTempC('Pune');
    Test.stopTest();

    System.assertEquals(22.5, t);
}

After Test.setMock, every call to Http.send() in production code is routed through WeatherMock.respond() instead of the network.

Timing matters

Register the mock before the code under test runs. Otherwise the actual callout fires (and fails). The conventional order:

  1. Set up data
  2. Test.setMock(...) — register the mock
  3. Test.startTest() — reset limits
  4. Call the code under test
  5. Test.stopTest() — force async, flush queues
  6. Assert

Two interfaces, two purposes

InterfaceFor
HttpCalloutMockAnything using Http.send() — REST callouts, raw HTTP, manual SOAP
WebServiceMockCode generated by WSDL2Apex — SOAP stubs

WSDL2Apex doesn’t call Http.send() directly; it goes through a different runtime path. That’s why SOAP needs WebServiceMock instead.

Helper: StaticResourceCalloutMock

For long JSON bodies, store the payload as a Static Resource and use the built-in helper:

StaticResourceCalloutMock mock = new StaticResourceCalloutMock();
mock.setStaticResource(WeatherSampleResponse);
mock.setStatusCode(200);
mock.setHeader('Content-Type', 'application/json');
Test.setMock(HttpCalloutMock.class, mock);

You don’t have to implement HttpCalloutMock — Salesforce ships this convenience class.

MultiStaticResourceCalloutMock — multiple endpoints

When code calls more than one endpoint and you want different bodies per endpoint:

MultiStaticResourceCalloutMock mock = new MultiStaticResourceCalloutMock();
mock.setStaticResource('https://api.weather.com/temp', WeatherTemp);
mock.setStaticResource('https://api.weather.com/forecast', WeatherForecast);
Test.setMock(HttpCalloutMock.class, mock);

Common interview follow-ups

  • What if my code calls two services? — One mock class with if/else on req.getEndpoint(), or use MultiStaticResourceCalloutMock.
  • Can I call Test.setMock twice in a test? — The last call wins for each interface type.
  • Does Test.setMock work outside test context? — No. It throws if called from production code.

Verified against: Apex Developer Guide — Testing HTTP Callouts. Last reviewed 2026-05-17 for Spring ‘26 release.