Saturday 5 October 2013

How to create mock HTTP response in Apex Test classes?


And hence the error was displayed: Methods defined as TestMethod do not support Web service call.

Making mock callouts for SOAP WS has been known to me. However creating mock response for HTTP/REST WS callout was not known to me.
While writing test classes for Order Capture apex classes, I come to learn this.

Although we could find this at any Salesforce communities and related blog, I am however writing and sharing it here as part of my experience.
Henceforth following is the way to make HTTP mock callouts and get fake HTTP response.

  • Provide an implementation for the HttpCalloutMock interface (this interface enables sending fake responses when testing HTTP callouts) to specify the response sent in the respond method, which the Apex runtime calls to send a response for a callout.

     global class YourHttpCalloutMockImpl implements HttpCalloutMock {
         global HTTPResponse respond(HTTPRequest req) {
             // Create a fake response.
             // Set response values, and
             // return response.
         }
     }

Note:
  • The class that implements the HttpCalloutMock interface can be either global or public.
  • You can annotate this class with @isTest since it will be used only in test context. In this way, you can exclude it from your organization’s code size limit of 3 MB.


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.


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.

  • /* Apex class making a callout */

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

  • /* MockResponse class implementing the HttpCalloutMock interface */

@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/endpoint', 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;
    }
}

  • /* Test Class getting fake response  from the class MockHttpResponseGenerator that implements HttpCalloutMock */

@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');
         String actualResponseBody = res.getBody();
         String expectedResponseBody = '{"foo":"bar"}';
         System.assertEquals(actualResponseBody, expectedResponseBody);
        System.assertEquals(200, res.getStatusCode());
    }
}



Happy Apex Coding and Testing! 

No comments:

Post a Comment

Thank you for visiting. Your comments are highly appreciated.