Methods defined as TestMethod do not support Web service callouts. This is the error that you will encounter when you run a test for an Apex class that makes a callout. The error being quite descriptive, it becomes obvious that you cannot directly test and/or have a coverage for the piece of code that makes a callout. To fix this we have 2 options. First one is a quick hack where you skip callout and set a mock response. The second option also involves mocking but instead of straightaway mocking the response, we mock the endpoint for callout


Option#1 - Test.isRunningTest()

So is there no way to have above 75% coverage and push such a code (that makes a callout) to production environment. Test.isRunningTest() comes to rescue. This method returns true if the currently executing code was called by code contained in a test method, false otherwise. So the workaround is simply to enclose the code blocks that are related to a Callout in an if condition as shown below.

...
HttpResponse res;
String JSONContent = '<sample JSON string of the response>';
            
if(!Test.isRunningTest()){
  req.setEndpoint('<endpoint url>');
  req.setMethod('GET');
  res = http.send(req);
  JSONContent = res.getBody();
}
...

The callout code will be executed only when the execution isn't from a test context; in which case the hard-coded JSON string will be used as JSON content. Make sure that you pass a real JSON string so that there is sufficient coverage without any Null pointer exceptions.


Option#2 - Implement HttpCalloutMock interface

Below is an example class that implements HttpCalloutMock interface. The interface consists of just one method respond that accepts HttpRequest as parameter and returns HttpResponse. The method need no implement the functionality of the actual endpoint but just need to mock it. And thereby set the status code and response body accordingly.

global class MyCalloutMock implements HttpCalloutMock{
        global HttpResponse respond(HTTPRequest req){
            HttpResponse res = new HttpResponse();
            
            res.setStatus('ok');
            res.setStatusCode(200);
            res.setBody('<json string>');
            return res;
            
        }
}

The next step after this is tell the test class to make the test method hit the mock endpoint instead of the actual one. We do this by the following code snippet.

Test.startTest();
    Test.setMock(HttpCalloutMock.class,new MyCalloutMock());
Test.stopTest();

The rest of the test method can have the blow code to set the HttpRequest and HttpResponse context and optionally URL parameters before getting the actual callout apex code executed.

String baseUrl =  URL.getOrgDomainUrl().toExternalForm();
RestRequest request = new RestRequest();
RestResponse response = new RestResponse();

request.requestUri = baseUrl + '<optional uri>';
request.params.put('<some key>', '<some value>');
request.httpMethod = 'GET'; //or other HTTP methods
		
RestContext.request = request;
RestContext.response = response;
        
// Call your class code that has the callout code;
System.assert(RestContext.response.responseBody,'<expected response>');
You’ve successfully subscribed to inteygrate
Welcome back! You’ve successfully signed in.
Great! You’ve successfully signed up.
Your link has expired
Success! Check your email for magic link to sign-in.