HttpCalloutMock Interface where there is more than 1 callout

Here is some background- I have an apex future method which is being called from an trigger. The future method then performs 3 different http calls to an external system (same endpoints). All requests have different body. Here is how it looks like-

public Static Void MyCallOut{
   String session= callout1();
   callout2(session);
   If(condition)   
      callout3(session);
   else
      callout4(session);
}

Everything works well.

I am trying to write test class for this using “HttpCalloutMock Interface”, and using this as reference.
Here is my MockHttpResponseGenerator, which I intend to call from my test class-

@isTest
global class MockHttpResponseGenerator implements HttpCalloutMock{
    // Implement this interface method
    global HTTPResponse respond(HTTPRequest req) {

        // Create a fake response
        HttpResponse res = new HttpResponse();
        res.setHeader('Content-Type', 'text/xml');
        res.setBody('<soapenv:Envelope>'+
                '<soapenv:Body><re:sessionId>BBE099E0392E6509B43</re:sessionId>'+
                '</soapenv:Body></soapenv:Envelope>');
        res.setStatusCode(200);
        return res;
    }
}

Now my questions is, How can I or Is there a way to make it work so that the HttpCalloutMock returns different responses for different calls? or Is there something I am missing?

P.S. I know this can be achieved by having separate mockcallresponse class to be called from the main class when isRunningTest is true. But, I want to if the same can be achieved without contaminating my main code.

Thanks

Answer

Salesforce passes in the HTTPRequest made by the logic your testing into the mock implementation to help with this type of requirement. So in the HttpCalloutMock.respond method implementation. You can call req.getBody() and condition the response based on that, here is an example…

@IsTest
private with sharing class MultiHttpMockTest 
{
    public class MockHttpResponseGenerator implements HttpCalloutMock
    {
        public HTTPResponse respond(HTTPRequest req) 
        {   
            HttpResponse res = new HttpResponse();
            res.setHeader('Content-Type', 'text/xml');
            if(req.getBody().contains('Call 1'))
                res.setBody('<soapenv:Envelope><soapenv:Body>Response 1</soapenv:Body></soapenv:Envelope>');
            else if(req.getBody().contains('Call 2'))
                res.setBody('<soapenv:Envelope><soapenv:Body>Response 2</soapenv:Body></soapenv:Envelope>');
            else if(req.getBody().contains('Call 3'))
                res.setBody('<soapenv:Envelope><soapenv:Body>Response 3</soapenv:Body></soapenv:Envelope>');            
            res.setStatusCode(200);
            return res;
        }
    }

    public static testmethod void testMultiMockResponse()
    {
        // Set single mock implementation that responds dynamically to different requests
        Test.setMock(HttpCalloutMock.class, new MockHttpResponseGenerator());

        // Frst request
        Http h = new Http();        
        HttpRequest req1 = new HttpRequest();
        req1.setEndpoint('http://mygreatservice.com/foo/bar');
        req1.setMethod('POST');
        req1.setBody('<soapenv:Envelope><soapenv:Body>Call 1</soapenv:Body></soapenv:Envelope>');
        HttpResponse res1 = h.send(req1);
        System.assertEquals('<soapenv:Envelope><soapenv:Body>Response 1</soapenv:Body></soapenv:Envelope>', res1.getBody());

        // Second request       
        HttpRequest req2 = new HttpRequest();
        req2.setEndpoint('http://mygreatservice.com/foo/bar');
        req2.setMethod('POST');
        req2.setBody('<soapenv:Envelope><soapenv:Body>Call 2</soapenv:Body></soapenv:Envelope>');
        HttpResponse res2 = h.send(req2);
        System.assertEquals('<soapenv:Envelope><soapenv:Body>Response 2</soapenv:Body></soapenv:Envelope>', res2.getBody());

        // Third request        
        HttpRequest req3 = new HttpRequest();
        req3.setEndpoint('http://mygreatservice.com/foo/bar');
        req3.setMethod('POST');
        req3.setBody('<soapenv:Envelope><soapenv:Body>Call 3</soapenv:Body></soapenv:Envelope>');
        HttpResponse res3 = h.send(req3);
        System.assertEquals('<soapenv:Envelope><soapenv:Body>Response 3</soapenv:Body></soapenv:Envelope>', res3.getBody());                    
    }
}

Attribution
Source : Link , Question Author : Sai , Answer Author : Andrew Fawcett

Leave a Comment