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— eitherHttpCalloutMock.classorWebServiceMock.classinstance— 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:
- Set up data
Test.setMock(...)— register the mockTest.startTest()— reset limits- Call the code under test
Test.stopTest()— force async, flush queues- Assert
Two interfaces, two purposes
| Interface | For |
|---|---|
HttpCalloutMock | Anything using Http.send() — REST callouts, raw HTTP, manual SOAP |
WebServiceMock | Code 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/elseonreq.getEndpoint(), or useMultiStaticResourceCalloutMock. - Can I call
Test.setMocktwice in a test? — The last call wins for each interface type. - Does
Test.setMockwork 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.