0% found this document useful (0 votes)
117 views5 pages

Apex HTTP Callout Testing Guide

The document discusses how to test HTTP callouts in Apex by mocking the callout response. It provides two methods: 1. Implementing the HttpCalloutMock interface to return a fake response. The test sets the mock callout mode and verifies the response. 2. Using the StaticResourceCalloutMock class to specify the response body in a static resource. The test sets the mock callout to use this resource and verifies the response. It also introduces the MultiStaticResourceCalloutMock class to mock multiple endpoints using different static resources for each response body.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
117 views5 pages

Apex HTTP Callout Testing Guide

The document discusses how to test HTTP callouts in Apex by mocking the callout response. It provides two methods: 1. Implementing the HttpCalloutMock interface to return a fake response. The test sets the mock callout mode and verifies the response. 2. Using the StaticResourceCalloutMock class to specify the response body in a static resource. The test sets the mock callout to use this resource and verifies the response. It also introduces the MultiStaticResourceCalloutMock class to mock multiple endpoints using different static resources for each response body.
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 5

Reference Apex Classes

Now that you have specified the values of the fake response, instruct the Apex runtime to send this fake response by calling
Test.setMock in your test method. For the first argument, pass HttpCalloutMock.class, and for the second argument,
pass a new instance of your interface implementation of HttpCalloutMock, as follows:

Test.setMock(HttpCalloutMock.class, new YourHttpCalloutMockImpl());

After this point, if an HTTP callout is invoked in test context, the callout is not made and you receive the mock response you
specified in the respond method implementation.
Note: If the code that performs the callout is in a managed package, you must call Test.setMock from a test
method in the same package with the same namespace to mock the callout.

This is a full example that shows how to test an HTTP callout. The interface implementation
(MockHttpResponseGenerator) is listed first. It is followed by a class containing the test method and another containing
the method that the test calls. The testCallout test method sets the mock callout mode by calling Test.setMock before
calling getInfoFromExternalService. It then verifies that the response returned is what the implemented respond
method sent. Save each class separately and run the test in CalloutClassTest.

@isTest
global class MockHttpResponseGenerator implements HttpCalloutMock {
// Implement this interface method
global HTTPResponse respond(HTTPRequest req) {
// Optionally, only send a mock response for a specific endpoint
// and method.
System.assertEquals('http://api.salesforce.com/foo/bar', req.getEndpoint());
System.assertEquals('GET', req.getMethod());

// Create a fake response


HttpResponse res = new HttpResponse();
res.setHeader('Content-Type', 'application/json');
res.setBody('{"foo":"bar"}');
res.setStatusCode(200);
return res;
}
}

public class CalloutClass {


public static HttpResponse getInfoFromExternalService() {
HttpRequest req = new HttpRequest();
req.setEndpoint('http://api.salesforce.com/foo/bar');
req.setMethod('GET');
Http h = new Http();
HttpResponse res = h.send(req);
return res;
}
}

@isTest
private class CalloutClassTest {
@isTest static void testCallout() {
// Set mock callout class
Test.setMock(HttpCalloutMock.class, new MockHttpResponseGenerator());

// Call method to test.


// This causes a fake response to be sent
// from the class that implements HttpCalloutMock.
HttpResponse res = CalloutClass.getInfoFromExternalService();

// Verify response received contains fake values


String contentType = res.getHeader('Content-Type');
System.assert(contentType == 'application/json');

622
Reference Apex Classes

String actualValue = res.getBody();


String expectedValue = '{"foo":"bar"}';
System.assertEquals(actualValue, expectedValue);
System.assertEquals(200, res.getStatusCode());
}
}

See Also:
Testing HTTP Callouts Using Static Resources
HttpCalloutMock Interface

Testing HTTP Callouts Using Static Resources


You can test HTTP callouts by specifying the body of the response you’d like to receive in a static resource and using one of
two built-in classes—StaticResourceCalloutMock or MultiStaticResourceCalloutMock.

Testing HTTP Callouts Using StaticResourceCalloutMock


Apex provides the built-in StaticResourceCalloutMock class that you can use to test callouts by specifying the response
body in a static resource. When using this class, you don’t have to provide your own implementation of the HttpCalloutMock
interface. Instead, just create an instance of StaticResourceCalloutMock and set the static resource to use for the response
body, along with other response properties, like the status code and content type.
First, you must create a static resource from a text file to contain the response body:
1. Create a text file that contains the response body to return. The response body can be an arbitrary string, but it must match
the content type, if specified. For example, if your response has no content type specified, the file can include the arbitrary
string abc. If you specify a content type of application/json for the response, the file content should be a JSON string,
such as {"hah":"fooled you"}.
2. Create a static resource for the text file:
a. Click Develop > Static Resources, and then New Static Resource.
b. Name your static resource.
c. Choose the file to upload.
d. Click Save.

To learn more about static resources, see “Defining Static Resources” in the Salesforce online help.
Next, create an instance of StaticResourceCalloutMock and set the static resource, and any other properties.

StaticResourceCalloutMock mock = new StaticResourceCalloutMock();


mock.setStaticResource('myStaticResourceName');
mock.setStatusCode(200);
mock.setHeader('Content-Type', 'application/json');

In your test method, call Test.setMock to set the mock callout mode and pass it HttpCalloutMock.class as the first
argument, and the variable name that you created for StaticResourceCalloutMock as the second argument.

Test.setMock(HttpCalloutMock.class, mock);

After this point, if your test method performs a callout, the callout is not made and the Apex runtime sends the mock response
you specified in your instance of StaticResourceCalloutMock.

623
Reference Apex Classes

Note: If the code that performs the callout is in a managed package, you must call Test.setMock from a test
method in the same package with the same namespace to mock the callout.

This is a full example containing the test method (testCalloutWithStaticResources) and the method it is testing
(getInfoFromExternalService) that performs the callout. Before running this example, create a static resource named
mockResponse based on a text file with the content {"hah":"fooled you"}. Save each class separately and run the
test in CalloutStaticClassTest.

public class CalloutStaticClass {


public static HttpResponse getInfoFromExternalService(String endpoint) {
HttpRequest req = new HttpRequest();
req.setEndpoint(endpoint);
req.setMethod('GET');
Http h = new Http();
HttpResponse res = h.send(req);
return res;
}
}

@isTest
private class CalloutStaticClassTest {
@isTest static void testCalloutWithStaticResources() {
// Use StaticResourceCalloutMock built-in class to
// specify fake response and include response body
// in a static resource.
StaticResourceCalloutMock mock = new StaticResourceCalloutMock();
mock.setStaticResource('mockResponse');
mock.setStatusCode(200);
mock.setHeader('Content-Type', 'application/json');

// Set the mock callout mode


Test.setMock(HttpCalloutMock.class, mock);

// Call the method that performs the callout


HTTPResponse res = CalloutStaticClass.getInfoFromExternalService(
'http://api.salesforce.com/foo/bar');

// Verify response received contains values returned by


// the mock response.
// This is the content of the static resource.
System.assertEquals('{"hah":"fooled you"}', res.getBody());
System.assertEquals(200,res.getStatusCode());
System.assertEquals('application/json', res.getHeader('Content-Type'));
}
}

Testing HTTP Callouts Using MultiStaticResourceCalloutMock


Apex provides the built-in MultiStaticResourceCalloutMock class that you can use to test callouts by specifying the
response body in a static resource for each endpoint. This class is similar to StaticResourceCalloutMock except that it
allows you to specify multiple response bodies. When using this class, you don’t have to provide your own implementation of
the HttpCalloutMock interface. Instead, just create an instance of MultiStaticResourceCalloutMock and set the
static resource to use per endpoint. You can also set other response properties like the status code and content type.
First, you must create a static resource from a text file to contain the response body. See the procedure outlined in Testing
HTTP Callouts Using StaticResourceCalloutMock.
Next, create an instance of MultiStaticResourceCalloutMock and set the static resource, and any other properties.

MultiStaticResourceCalloutMock multimock = new MultiStaticResourceCalloutMock();


multimock.setStaticResource('http://api.salesforce.com/foo/bar', 'mockResponse');

624
Reference Apex Classes

multimock.setStaticResource('http://api.salesforce.com/foo/sfdc', 'mockResponse2');
multimock.setStatusCode(200);
multimock.setHeader('Content-Type', 'application/json');

In your test method, call Test.setMock to set the mock callout mode and pass it HttpCalloutMock.class as the first
argument, and the variable name that you created for MultiStaticResourceCalloutMock as the second argument.

Test.setMock(HttpCalloutMock.class, multimock);

After this point, if your test method performs an HTTP callout to one of the endpoints
http://api.salesforce.com/foo/bar or http://api.salesforce.com/foo/sfdc, the callout is not made and
the Apex runtime sends the corresponding mock response you specified in your instance of
MultiStaticResourceCalloutMock.
This is a full example containing the test method (testCalloutWithMultipleStaticResources) and the method it is
testing (getInfoFromExternalService) that performs the callout. Before running this example, create a static resource
named mockResponse based on a text file with the content {"hah":"fooled you"} and another named
mockResponse2 based on a text file with the content {"hah":"fooled you twice"}. Save each class separately and
run the test in CalloutMultiStaticClassTest.

public class CalloutMultiStaticClass {


public static HttpResponse getInfoFromExternalService(String endpoint) {
HttpRequest req = new HttpRequest();
req.setEndpoint(endpoint);
req.setMethod('GET');
Http h = new Http();
HttpResponse res = h.send(req);
return res;
}
}

@isTest
private class CalloutMultiStaticClassTest {
@isTest static void testCalloutWithMultipleStaticResources() {
// Use MultiStaticResourceCalloutMock to
// specify fake response for a certain endpoint and
// include response body in a static resource.
MultiStaticResourceCalloutMock multimock = new MultiStaticResourceCalloutMock();
multimock.setStaticResource(
'http://api.salesforce.com/foo/bar', 'mockResponse');
multimock.setStaticResource(
'http://api.salesforce.com/foo/sfdc', 'mockResponse2');
multimock.setStatusCode(200);
multimock.setHeader('Content-Type', 'application/json');

// Set the mock callout mode


Test.setMock(HttpCalloutMock.class, multimock);

// Call the method for the first endpoint


HTTPResponse res = CalloutMultiStaticClass.getInfoFromExternalService(
'http://api.salesforce.com/foo/bar');
// Verify response received
System.assertEquals('{"hah":"fooled you"}', res.getBody());

// Call the method for the second endpoint


HTTPResponse res2 = CalloutMultiStaticClass.getInfoFromExternalService(
'http://api.salesforce.com/foo/sfdc');
// Verify response received
System.assertEquals('{"hah":"fooled you twice"}', res2.getBody());

625
Reference Apex Classes

}
}

See Also:
Testing HTTP Callouts by Implementing the HttpCalloutMock Interface
MultiStaticResourceCalloutMock Methods
StaticResourceCalloutMock Methods

Performing DML Operations and Mock Callouts


By default, callouts aren’t allowed after DML operations in the same transaction because DML operations result in pending
uncommitted work that prevents callouts from executing. Sometimes, you might want to insert test data in your test method
using DML before making a callout. To enable this, enclose the portion of your code that performs the callout within
Test.startTest and Test.stopTest statements. The Test.startTest statement must appear before the Test.setMock
statement. Also, the calls to DML operations must not be part of the Test.startTest/Test.stopTest block.
DML operations that occur after mock callouts are allowed and don’t require any changes in test methods.
The DML operations support works for all implementations of mock callouts using: the HttpCalloutMock interface and
static resources (StaticResourceCalloutMock or MultiStaticResourceCalloutMock). The following example uses
an implemented HttpCalloutMock interface but you can apply the same technique when using static resources.

Performing DML Before Mock Callouts


This example is based on the HttpCalloutMock example provided earlier. The example shows how to use Test.startTest
and Test.stopTest statements to allow DML operations to be performed in a test method before mock callouts. The test
method (testCallout) first inserts a test account, calls Test.startTest, sets the mock callout mode using Test.setMock,
calls a method that performs the callout, verifies the mock response values, and finally, calls Test.stopTest.

@isTest
private class CalloutClassTest {
@isTest static void testCallout() {
// Perform some DML to insert test data
Account testAcct = new Account('Test Account');
insert testAcct;

// Call Test.startTest before performing callout


// but after setting test data.
Test.startTest();

// Set mock callout class


Test.setMock(HttpCalloutMock.class, new MockHttpResponseGenerator());

// Call method to test.


// This causes a fake response to be sent
// from the class that implements HttpCalloutMock.
HttpResponse res = CalloutClass.getInfoFromExternalService();

// Verify response received contains fake values


String contentType = res.getHeader('Content-Type');
System.assert(contentType == 'application/json');
String actualValue = res.getBody();
String expectedValue = '{"foo":"bar"}';
System.assertEquals(actualValue, expectedValue);
System.assertEquals(200, res.getStatusCode());

Test.stopTest();

626

You might also like