Mocking Multiple HTTP Requests to the Same Endpoint

mockMy Blog posts are like buses. You don’t see one for ages and then two come along at once.

I was musing, like you do, what to do when Unit Testing a service that makes successive call-outs to the same endpoint. If the endpoints were different then you could use the MultiStaticResourceCalloutMock class. But what if you need to make two calls to the same endpoint?

So take this bit of code:

public with sharing class MyCallout
{
	public static Boolean doCallouts()
	{
		Boolean isDog = isDog('Toto');
		Boolean isHuman = isHuman('Dorothy');

		return isDog && isHuman;
	}

	private static Boolean isDog(String name)
	{
		return getSpecies(name) == 'dog';
	}

	private static Boolean isHuman(String name)
	{
		return getSpecies(name) == 'human';
	}

	private static String getSpecies(String name)
	{
		HttpRequest req = new HttpRequest();

		req.setMethod('GET');
		req.setHeader('Content-type', 'application/json');
        req.setHeader('Accept', 'application/json');

		req.setEndpoint('https://somewhereovertherainbow.com/wherestoto');

		req.setBody('{"name" : "' + name + '"}');

		Http http = new Http();

		HttpResponse res = http.send(req);

		if (res.getStatusCode() != 200)
		{
			return null;
		}

		Map marshalledResponse = (Map)JSON.deserializeUntyped(res.getBody());

		String species = (String)marshalledResponse.get('species');

		return species;
	}
}

It makes two successive calls to the same endpoint to resolve the species of a given Wizard Of Oz character. If they both match it returns true. Simple enough, but what about testing it?

In our unit test we create our mock response class (implementing the HttpCalloutMock interface) and add a simple constructor that takes a list of responses.

The respond method then returns the responses in sequence each time it’s called. Easy peasy lemon squeezy.

@isTest
private class MyCalloutTest
{
	@isTest static void testDoCallouts_pass()
	{
		// Create the responses in the correct sequence
		String[] responses = new String[] {
			'{ "species" : "dog" }',
			'{ "species" : "human" }'
		};

        // Set mock callout class
        Test.setMock(HttpCalloutMock.class, new MockResponse(responses));

		Boolean result = MyCallout.doCallouts();

        System.assertEquals(true, result);
	}

	@isTest static void testDoCallouts_fail()
	{
		// Create the responses in the wrong sequence
		String[] responses = new String[] {
			'{ "species" : "human" }',
			'{ "species" : "dog" }'
		};

        // Set mock callout class
        Test.setMock(HttpCalloutMock.class, new MockResponse(responses));

		Boolean result = MyCallout.doCallouts();

        System.assertEquals(false, result);
	}

    public class MockResponse
        implements HttpCalloutMock
    {
    	private Integer m_responseIndex;
    	private String[] m_reponses;

    	public MockResponse(String[] reponses)
    	{
    		m_responseIndex = 0;
    		m_reponses = reponses;
    	}

        public HTTPResponse respond(HTTPRequest req)
        {
            HttpResponse res = new HttpResponse();
            res.setHeader('Content-Type', 'application/json');

            // Return the next response in the list
			String reponse = m_reponses[m_responseIndex];
			m_responseIndex ++;

            res.setBody(reponse);
            res.setStatusCode(200);

            return res;
        }
    }
}

You could adapt this pattern to provide different response codes in the same way.

Advertisements

Author, brainstormer, coder, dad, explorer, four chord trickster, gig goer, home worker, inquisitor, joker, knowledge seeker, likes: marmite, note scribbler, opinionator, poet, quite likes converse, roller skater, six music listener, tea drinker, urban dweller, vinyl spinner, word wrangler, x-factor hater, Yorkshireman (honorary), zombie slayer (lie).

Tagged with: , , ,
Posted in apex, code, force.com, salesforce, Uncategorized
About Me
Product Services Developer at:
FinancialForce.com
All views expressed here are my own. More about me and contact details here.

Enter your email address to follow this blog and receive notifications of new posts by email.

Copyright (there isn’t any, feel free to reuse!)

CC0
To the extent possible under law, Tony Scott has waived all copyright and related or neighboring rights to MeltedWires.com Examples and Code Samples. This work is published from: United Kingdom.

%d bloggers like this: