I have an extension to a vf page which makes an http call to a web service. I am tying to follow the salesforce guide for setting up the HttpCalloutMock Interface, though I don't quite get how to set it up for my specific case. Some specific questions I have:
- Does the MockHttpResponse and test class need to mirror what I have in my extension method? I mean, do I need to include Blob, API keys, etc?
- How should I set the HTTP response in my test class, as it is I get the error "Method does not exist or incorrect signature". I also try to set it as String res = ClinicalStudySetupExtension.callRestEndPoint();, but that doesn't change anything either.
My extension
public with sharing class ClinicalStudySetupExtension {
private String studyJson;
private String result;
private String protocolNumber;
public String query {get; set;}
public Boolean searched {get; set;}
public Clinical_Study__c cStudy {get; set;}
private ApexPages.StandardController std {get; set;}
//controller
public ClinicalStudySetupExtension(ApexPages.StandardController std) {
this.std = std;
this.studyJson = callRestEndPoint();
query = '';
searched=false;
String queryStr=ApexPages.currentPage().getParameters().get('query');
if (queryStr!=null)
{
protocolNumber=queryStr;
runSearch();
}
}
public pageReference runSearch() {//runSearch takes the input 'query' and passes it to the REST api call
searched=true;
String searchStr = ''+query+'';
system.debug('Study name: ' + query);
protocolNumber = searchStr.deleteWhitespace();
this.studyJson = callRestEndPoint();
return null;
}
private string callRestEndPoint() {//the rest api call generates a json string and passes it to the json parser
Http h = new Http();
HttpRequest req = new HttpRequest();
HttpResponse res = new HttpResponse();
String username = 'ex';
String password = 'ex';
Blob headerValue = Blob.valueOf(username + ':' + password);
String authorizationHeader = 'Basic ' + EncodingUtil.base64Encode(headerValue);
req.setClientCertificateName('CN');
req.setHeader('Authorization', authorizationHeader);
req.setHeader('Api-Key', '777..');
req.setTimeout(120000);
req.setMethod('GET');
req.setEndpoint('https://example.com/study/'+protocolNumber);
String result = '';
try{
res = h.send(req);
result = res.getBody();
}
catch(System.CalloutException e){
result = res.toString();
}
return result;
}
My test class
public static testMethod 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 = ClinicalStudySetupExtension.callRestEndPoint();
// Verify response received contains fake values
String contentType = res.getHeader('Content-Type');
System.assert(contentType == 'application/json');
String actualValue = res.getBody();
String expectedValue = '{"study":{"moleculeDescription":"RONTALIZUMAB","protocolTitle":"IMM","protocolNumber":"GA00806","studyName":"Interferon alpha in SLE Phase II LCM Option","therapeuticArea":"INFLAMMATORY,AUTOIMMUNE&BONE","startDate":"2009-03-25","endDate":"2013-08-22"}}';
System.assertEquals(actualValue, expectedValue);
System.assertEquals(200, res.getStatusCode());
}
The MockHttpResponseGenerator
@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('https://example.com/study/GA00806', req.getEndpoint());
System.assertEquals('GET', req.getMethod());
// Create a fake response
HttpResponse res = new HttpResponse();
res.setHeader('Content-Type', 'application/json');
res.setBody('{"study":{"moleculeDescription":"RONTALIZUMAB","protocolTitle":"IMM","protocolNumber":"GA00806","studyName":"Interferon alpha in SLE Phase II LCM Option","therapeuticArea":"INFLAMMATORY,AUTOIMMUNE&BONE","startDate":"2009-03-25","endDate":"2013-08-22"}}');
res.setStatusCode(200);
return res;
}
}
Best Answer
The MOCKHTTP class ss returning EXACTLY what the regular Endpoint would return.
Since your class
ClinicalStudySetupExtension.callRestEndPoint()
is PRIVATE Method ofClinicalStudySetupExtension
you simply need to instantiate your controller as it will call the method which in turn will make the callout thus getting a response based on the HTTPMOCK class and process based on the controllerThe point of the HTTPMOCK is to return an HTTPResponse just like an endpoint would.
Also, no need for a system assert in your HTTP Mock Class. You are going to construct and return different responses based on the request parameters sent to endpoint by whatever class / method calls it. You can use the same HTTPMOCK class for several methods from a related class that may use PUT, GET, POST, etc or different endpoints and wrap them all up in one HTPMOCK class to generate the appropriate response.
Once you instantiate the controller assert the value of 'this.studyJson' for the value of
{"study":{"moleculeDescription":"RONTALIZUMAB","protocolTitle":"IMM","protocolNumber":"GA00806","studyName":"Interferon alpha in SLE Phase II LCM Option","therapeuticArea":"INFLAMMATORY,AUTOIMMUNE&BONE","startDate":"2009-03-25","endDate":"2013-08-22"}}
since this is what your controller sets based on the response.Clear as mud?