subscribe our youtube channel popup

Testing Web Services Callouts in Salesforce

Web services callouts are essential for integrating Salesforce with external systems. They allow Salesforce applications to interact with external APIs, fetch data, and perform real-time operations. However, testing these callouts presents challenges, as they depend on third-party systems that may be unreliable, slow, or unavailable during development. Join us to learn about Testing Web Services Callouts in Salesforce.

To address these issues, Salesforce provides tools and best practices to simulate web service callouts, ensuring applications are robust and reliable. In this article, we will explore different techniques for testing web service callouts in Salesforce and how to manage governor limits.

Understanding Web Service Callouts in Salesforce

A callout is an HTTP request from Salesforce to an external web service. There are two main types:

  • SOAP Callouts: Use XML-based protocols for structured communication.
  • REST Callouts: Use lightweight JSON or XML for seamless data exchange.

Callouts are executed within Salesforce’s execution context and require asynchronous handling in batch or trigger scenarios.

Learn about Salesforce Integration.

Challenges in Testing Web Service Callouts

Testing web service callouts presents several challenges like:

  1. External System Dependencies: The availability and response of the external system may affect tests.
  2. API Rate Limits: Repeated testing may exceed callout limits imposed by the external service.
  3. Data Inconsistency: The external service data may change, affecting test repeatability.
  4. Performance Issues: Slow response times from external services may impact test execution.

Techniques for Testing Web Service Callouts

WeatherService class:

public class WeatherService {
    public static String getWeather(String city) {
        Http http = new Http();
        HttpRequest request = new HttpRequest();
        request.setEndpoint('https://api.example.weather.com');
        request.setMethod('GET');
        HttpResponse response = http.send(request);
        return response.getBody();
    }
}

1. Using Mock Callouts

Salesforce requires the use of mock callouts to test HTTP callouts. The HttpCalloutMock interface allows developers to define predictable responses for testing.

Example:

@isTest
private class WeatherServiceTest {
    public class MockWeatherCallout implements HttpCalloutMock {
        public HttpResponse respond(HttpRequest req) {
            //simulating an api response
            HttpResponse mockRes = new HttpResponse();
            //set response values
            mockRes.setStatusCode(200);
            mockRes.setBody(‘{“temperature”: “30°C”, “condition”: “Sunny”}’);
            //returning mock response
            return mockRes;
        }
    }
    
    @isTest
    static void testWeatherService() {
         //instructing the Apex runtime to send the mock response
        Test.setMock(HttpCalloutMock.class, new MockWeatherCallout());
        // calling the method under test
        String result = WeatherService.getWeather(‘NewYork’);
        // validating the response
        System.assert(result.contains(‘30°C’));
    }
}

The above class is designed to test the WeatherService class, which makes an HTTP callout to retrieve weather data. The test uses a mock response to simulate the external API call, ensuring that the test is isolated from external dependencies and runs consistently.

The testWeatherService method tests the WeatherService.getWeather method by simulating an external API call using the mock response.

  • Test.setMock(HttpCalloutMock.class, new MockWeatherCallout()); — Tells Apex to use the MockWeatherCallout class to simulate any HTTP callouts made during the test.
  • String result = WeatherService.getWeather(‘NewYork’); — Calls the getWeather method of the WeatherService class. Due to the mock setup, instead of making an actual HTTP call, it receives the mock response.
  • System.assert(result.contains(‘30°C’)); — Checks if the response from WeatherService.getWeather contains the expected temperature (“30°C”). If the condition is met, the test succeeds; otherwise, it does not.

2. Using Static Resources for Mock Responses

Static resources can store JSON/XML responses to simulate actual API calls. This method ensures that responses remain consistent across test runs.

Example:

The first step is to create a static resource called MockWeatherResponse.

  1. Create a JSON file with the following content:

mock_weather.json

{
    “temperature”: “28°C”,
    “condition”: “Cloudy”
}
  1. Navigate to the Setup > Quick Find > Static Resources.
  2. Click ‘New’. Name the static resource as ‘MockWeatherResponse’ and upload this JSON file.
  3. Save it.

   Now, to use this static resource in a test class, here’s how you can:

@isTest
private class WeatherServiceTestStaticResource {
    public class MockWeatherCalloutFromStaticResource implements HttpCalloutMock {
        public HTTPResponse respond(HTTPRequest req) {
            // load the mock response from the static resource
            StaticResource resource = [SELECT Body FROM StaticResource WHERE Name = ‘MockWeatherResponse’];
            String jsonResponse = resource.Body.toString();

            // simulating and returning a mock response
            HttpResponse mockRes = new HttpResponse();
            mockRes.setStatusCode(200);
            mockRes.setBody(jsonResponse);
            return mockRes;
        }
    }

    @isTest
    static void testWeatherService() {
    // set the mock response
    Test.setMock(HttpCalloutMock.class, new MockWeatherCalloutFromStaticResource());
    // calling the method under test
    String result = WeatherService.getWeather(‘London’);
    // validating the response
    System.assert(result.contains(‘28°C’), ‘Expected temperature not found’);
    System.assert(result.contains(‘Cloudy’), ‘Expected weather condition not found’);
    }
}

The above test class is designed to verify the WeatherService.getWeather method by simulating an external API response using a mock callout. Instead of calling a real API, it fetches a pre-defined response from a static resource in Salesforce.

StaticResource resource = [SELECT Body FROM StaticResource WHERE Name = ‘MockWeatherResponse’];             String jsonResponse = resource.Body.toString();These lines retrieve the static resource named MockWeatherResponse using SOQL and convert the binary Body of the resource into a string that contains JSON-formatted weather data.
HttpResponse mockRes = new HttpResponse(); mockRes.setStatusCode(200); mockRes.setBody(jsonResponse); return mockRes;These lines of code create and set mock response and return it.
@isTest static void testWeatherService() { Test.setMock(HttpCalloutMock.class, new MockWeatherCalloutFromStaticResource());   String result = WeatherService.getWeather(‘London’);   System.assert(result.contains(‘28°C’), ‘Expected temperature not found’); System.assert(result.contains(‘Cloudy’), ‘Expected weather condition not found’); }This block tests the callout by simulating an external API call that uses the mock response.

Managing Governor Limits with Limit Methods, Test.startTest() and Test.stopTest()

Test.startTest() and Test.stopTest()

When writing tests, use Test.startTest() and Test.stopTest() to simulate real-world conditions while resetting governor limits.

  • Test.startTest() marks the beginning of test execution and grants a fresh set of governor limits for all operations performed after it.
  • Test.stopTest() executes any pending asynchronous operations synchronously (e.g., future methods, batch jobs) before restoring the original governor limits.

For example, if a class executes 90 SOQL queries before Test.startTest(), it can still execute another 100 queries after Test.startTest(). Once Test.stopTest() is called, the original limit context resumes, allowing only 10 additional queries before hitting the SOQL limit of 100.

@isTest
private class WeatherServiceTest {
    public class MockWeatherCallout implements HttpCalloutMock {
        public HttpResponse respond(HttpRequest req) {
            HttpResponse mockRes = new HttpResponse();
            mockRes.setStatusCode(200);
            mockRes.setBody(‘{“temperature”: “30°C”, “condition”: “Sunny”}’);
            return mockRes;
        }
    }
    
    @isTest
    static void testWeatherService() {
        Test.setMock(HttpCalloutMock.class, new MockWeatherCallout());

        Test.startTest();  // Starts fresh governor limits
        String result = WeatherService.getWeather(‘NewYork’);
        Test.stopTest();  // Executes any pending callouts

        System.assert(result.contains(‘30°C’));
    }
}

Limit Methods

Salesforce enforces strict governor limits to maintain multi-tenant architecture efficiency. When testing web service callouts, the Limits methods help developers track API usage and ensure their code does not exceed these constraints.

There are two key limit methods related to web service callouts:

  • Limits.getCallouts() – Returns the number of callouts already used in the current execution context.
  • Limits.getLimitCallouts() – Returns the maximum number of callouts allowed in a single transaction (100 for synchronous Apex).

Example

@isTest
private class WeatherServiceTest {
    public class MockWeatherCallout implements HttpCalloutMock {
        public HttpResponse respond(HttpRequest req) {
            HttpResponse mockRes = new HttpResponse();
            mockRes.setStatusCode(200);
            mockRes.setBody(‘{“temperature”: “30°C”, “condition”: “Sunny”}’);
            return mockRes;
        }
    }
    
    @isTest
    static void testCalloutLimits() {
        Test.startTest();
        
        // Mocking the API response
        Test.setMock(HttpCalloutMock.class, new MockWeatherCallout());
        
        // Checking callout usage before making a request
        Integer beforeCallouts = Limits.getCallouts();
        System.debug(‘Callouts used before API request: ’ + beforeCallouts);
        
        // Simulated API request
        WeatherService.getWeather(‘New York’);
        
        // Checking callout usage after making a request
        Integer afterCallouts = Limits.getCallouts();
        System.debug(‘Callouts used after API request: ’ + afterCallouts);
        
        Test.stopTest();
        
        // Validate and log results
        if (beforeCallouts + 1 == afterCallouts) {
            System.debug(‘Validation Passed: Only one callout was made.’);
        } else {
            System.debug(‘Validation Failed: Unexpected number of callouts made.’);
        }

        if (afterCallouts <= Limits.getLimitCallouts()) {
            System.debug(‘Validation Passed: Callout limit not exceeded.’);
        } else {
            System.debug(‘Validation Failed: Callout limit exceeded!’);
        }

        // Standard assertions
        System.assertEquals(beforeCallouts + 1, afterCallouts, ‘Unexpected number of callouts made’);
        System.assert(afterCallouts <= Limits.getLimitCallouts(), ‘Callout limit exceeded!’);
    }
}

Output:

These methods help in testing callouts by:

  1. Monitoring API Call Consumption
  2. When testing batch processes or loops, using Limits.getCallouts() ensures the callout count does not exceed the limit of 100.
  3. It helps to identify excessive API calls and optimize them.
  4. Preventing Governor Limit Exceedance
  5. Use conditional checks to avoid hitting the limit.
  6. Validating Efficient Code Execution
  7. It helps ensure that an API-intensive method does not make unnecessary callouts.

By strategically using these methods, developers can accurately test bulk data operations, asynchronous jobs, and external API callouts while staying within Salesforce’s governance framework.

Conclusion

Testing web service callouts in Salesforce is essential for ensuring application stability. By using mock callouts, static resources, and proper test structures, developers can build robust integrations while avoiding dependencies on external systems. With the right testing strategies, teams can validate callout functionality, handle failures gracefully, and ensure consistent application behaviour across different environments. Hope this helped you to understand the Testing Web Services Callouts in Salesforce.

Sheima Latha J
Sheima Latha J
Articles: 27

Leave a Reply

Your email address will not be published. Required fields are marked *