When developing Salesforce integrations, Apex callouts are commonly used to communicate with external applications and REST APIs.
But there is one challenge: how do you test an API integration without making an actual HTTP request every time your test runs?
This is where Apex callout mocking becomes useful.
Salesforce provides the HttpCalloutMock interface, which allows developers to simulate API responses during test execution. This makes integration testing more reliable and helps achieve the required Apex test coverage.
Let's understand how it works with a practical example.
- Create an Apex Class for the REST API Callout
First, create an Apex class that sends an HTTP request to an external service.
public class ExternalApiService {
public static String getCustomerData() { Http http = new Http(); HttpRequest request = new HttpRequest(); request.setEndpoint( 'https://api.example.com/customers' ); request.setMethod('GET'); HttpResponse response = http.send(request); if (response.getStatusCode() == 200) { return response.getBody(); } throw new CalloutException( 'API request failed: ' + response.getStatusCode() ); } }
This example sends a GET request and returns the response body when the API responds successfully.
For production integrations, use a Salesforce Named Credential instead of hardcoding the endpoint. This helps manage authentication and endpoint configuration securely.
- Understand the HttpCalloutMock Interface
Salesforce does not allow test methods to make real HTTP callouts.
Instead, you can implement HttpCalloutMock to provide a simulated response.
The mock class implements the respond() method, which receives an HttpRequest and returns an HttpResponse.
This allows you to control the response without depending on an external API.
- Create a Mock Response Class
Here is a simple mock implementation:
@IsTest
global class CustomerApiMock implements HttpCalloutMock {
global HttpResponse respond(HttpRequest request) { HttpResponse response = new HttpResponse(); response.setStatusCode(200); response.setBody( '{"id":101,"name":"John Smith","status":"Active"}' ); return response; } }
This mock returns a successful response containing sample customer information.
You can create different mock classes to simulate successful responses, errors, empty responses, and other API scenarios.
- Write the Apex Test Class
Now use Test.setMock() to register the mock before executing the method that performs the callout.
@IsTest
private class ExternalApiServiceTest {
@IsTest static void testCustomerData() { Test.setMock( HttpCalloutMock.class, new CustomerApiMock() ); Test.startTest(); String result = ExternalApiService.getCustomerData(); Test.stopTest(); System.assert( result.contains('John Smith'), 'Expected customer name was not returned.' ); } }
When getCustomerData() executes, Salesforce uses the mock response instead of sending a real HTTP request.
This makes the test independent of external API availability.
- Test Different API Response Scenarios
A successful response is not enough to confirm that your integration handles errors correctly.
Your tests should also cover:
HTTP 400 – Bad Request.
HTTP 401 – Unauthorized.
HTTP 404 – Not Found.
HTTP 500 – Internal Server Error.
Empty or invalid response bodies.
Create separate mock responses and verify that your Apex class handles each situation as expected.
For example, you can simulate a server error by returning status code 500 and checking whether your application raises the expected exception.
- Verify the Request, Not Just the Response
A good integration test should also verify that Salesforce sends the correct request.
Inside the respond() method, you can inspect the incoming request:
System.assertEquals(
'GET',
request.getMethod()
);
System.assert(
request.getEndpoint().contains('/customers')
);
You can also verify headers, request parameters, and POST or PUT request bodies.
This helps identify issues where the API response is mocked correctly but the actual request is incorrectly configured.
- Follow These Best Practices
When building Apex integration tests, keep these points in mind:
Use HttpCalloutMock for HTTP callouts.
Test both successful and unsuccessful responses.
Validate request methods and endpoints.
Avoid depending on live external services.
Use meaningful test data.
Keep mock classes reusable where practical.
Store integration endpoints and authentication details in Named Credentials.
For callouts involving multiple requests or different responses, you can build more advanced mock classes that return responses based on the request details.
Final Thoughts
Apex callout mocking makes Salesforce integration testing more predictable and maintainable. By using HttpCalloutMock, developers can test API behavior without depending on external systems.
Start by creating a separate service class, implementing a mock response, and testing different HTTP scenarios. As integrations grow, reusable mock classes can make the test suite easier to maintain.
For more Salesforce development and integration guidance, explore iBirds Software Services.
What approach do you use to test REST API integrations in Salesforce: reusable mock classes or separate mocks for each test scenario?
