Using MultiStaticResourceCalloutMock

To test the Twitter code in the previous post, MultiStaticResourceCalloutMock turned out to be a great option (with one caveat – see below).

If you’re not familiar with Mock Callouts in general, it’s a relatively new feature from Salesforce to enable developers to test callouts without actually making a callout (since that isn’t allowed during test execution). Basically, we can tell Salesforce that when it sees a request to make a callout in a test to override it with the response specified by the Mock Callout Class.

But the Twitter code poses a tricky problem – the code actually makes TWO callouts – one to get the token, and one to retrieve the data. So instead of having to use some form of test.IsRunningTest() in the callout code to catch each callout and set the mock callout there, we can use MultiStaticResourceCalloutMock feature to specify a response for each endpoint referenced in our test up front.

To use MultiStaticResourceCalloutMock, we first have to create a static resource for each response we are going to get back. I find it easiest to can get the data for the response by making a call via the browser, or doing a debug in the logs for an actual response, and then amending the code as required to make sure I have the structure correct.

Then we can create our test method:

@isTest
private static void testTwitterSingle () {

//Set the Custom Settings for the endpoint and keys
List<social_media_settings__c> sms = new List<social_media_settings__c> ();
sms.add(new social_media_settings__c (
Name = 'Twitter',
URL__c = 'https://api.twitter.com/1.1/users/lookup.json?screen_name=',
API_Key__c = 'KEYPUBLIC',
API_Secret_Key__c = 'KEYPRIVATE'));

//Then create a test contact
Contact c = new Contact (
LastName = 'Test Twitter 1', 
Twitter_Username__c = 'britishboyindc');
insert c;

Now create a mock callout for each endpoint – each instance of  MultiStaticResourceCalloutMock takes two params – the endpoint, and the name of the relevant static response to use as the returned response:

MultiStaticResourceCalloutMock multimock = new MultiStaticResourceCalloutMock();
multimock.setStaticResource('https://api.twitter.com/oauth2/token', 'TwitterBearerResponse');
multimock.setStaticResource('https://api.twitter.com/1.1/users/lookup.json?screen_name=britishboyindc', 'TwitterResultsResponse');

We can also set different response params to test success/fail responses:

multimock.setStatusCode(200);
multimock.setHeader('Content-Type', 'application/json');

Before we set the mock callouts, we need to invoke the StartTest to ensure we don’t get the DML before Callouts error:

Test.starttest();
// Set the mock callout mode
 Test.setMock(HttpCalloutMock.class, multimock);

 //I can invoke the code via a button on a contact, so let's use the extension
 contactextension_bfc bfc = new contactextension_bfc(new ApexPages.StandardController(c)); 
bfc.updatesocialmedia();
Test.stoptest();

Then query for the Contact and check the followers were updated based on the data in the static response:

Contact tconfirm = [Select Id,
 Twitter_Followers__c FROM Contact
 WHERE Id = :c.Id];
 system.assertequals(170,tconfirm.Twitter_Followers__c);
 }

The one caveat to this approach is around testing batches. I can also call my twitter code via a batch if I want to update a bunch of contacts. But as of now Spring 13 Batches and Mock Resources don’t seem to play nicely together in tests. But looking at the release notes, Summer 13 fixes this,  so I’ll post again when I can confirm that.

 

Leave a Reply