function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Naomi HarmonNaomi Harmon 

Webhook Callout Trigger causing errors in all Test Classes

IT recently built some Apex triggers on our Lead, Account, and Opportunity objects that make a web callout whenever a record is inserted and/or updated. Now I'm trying to deploy some new triggers, and I'm creating some new Opportunities in my test class. My trigger and test class don't contain any callouts, but because of these other triggers that are in place, I'm getting hit with this error message:
Methods defined as TestMethod do not support Web service callouts 
Stack Trace: null

How can I fix this?? I've tried changing the triggers that contain the callouts by inserting the if(!test.isrunningtest()) before the callout, but that causes its own test class to fail with a null pointer exception.
Best Answer chosen by Naomi Harmon
Stas ChristiansenStas Christiansen
Hi Naomi, 

Since test classes do not support web service callouts, you have to take a more roundabout way of simulating the callout. 

The first thing you will want to do is to implement the HttpCalloutMock interface which will serve as the 'response' you will expect from the web service. In this class you will set some mock response values and then return them. 

Next you will want to call the mock class you just made from within the actual test class. Do this by calling: 
 
Test.setMock(HttpCalloutMock.class, new YourHttpCalloutMockImpl());
This part takes care of replacing the callout to the actual web service with a callout to the mock class you created in step 1.


Here is an example given by Salesforce documentation which outlines the various pieces in code form: 

YourSampleMockResponse:
 
@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('http://example.com/example/test', req.getEndpoint());
        System.assertEquals('GET', req.getMethod());
        
        // Create a fake response
        HttpResponse res = new HttpResponse();
        res.setHeader('Content-Type', 'application/json');
        res.setBody('{"example":"test"}');
        res.setStatusCode(200);
        return res;
    }
}

YourTestClass: 
 
@isTest
private class CalloutClassTest {
     @isTest static 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 = CalloutClass.getInfoFromExternalService();
        
        // Verify response received contains fake values
        String contentType = res.getHeader('Content-Type');
        System.assert(contentType == 'application/json');
        String actualValue = res.getBody();
        String expectedValue = '{"example":"test"}';
        System.assertEquals(actualValue, expectedValue);
        System.assertEquals(200, res.getStatusCode());
    }
}

Here is the documentation for the full explanation: https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_classes_restful_http_testing_httpcalloutmock.htm

Hope this helps!
 

All Answers

Stas ChristiansenStas Christiansen
Hi Naomi, 

Since test classes do not support web service callouts, you have to take a more roundabout way of simulating the callout. 

The first thing you will want to do is to implement the HttpCalloutMock interface which will serve as the 'response' you will expect from the web service. In this class you will set some mock response values and then return them. 

Next you will want to call the mock class you just made from within the actual test class. Do this by calling: 
 
Test.setMock(HttpCalloutMock.class, new YourHttpCalloutMockImpl());
This part takes care of replacing the callout to the actual web service with a callout to the mock class you created in step 1.


Here is an example given by Salesforce documentation which outlines the various pieces in code form: 

YourSampleMockResponse:
 
@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('http://example.com/example/test', req.getEndpoint());
        System.assertEquals('GET', req.getMethod());
        
        // Create a fake response
        HttpResponse res = new HttpResponse();
        res.setHeader('Content-Type', 'application/json');
        res.setBody('{"example":"test"}');
        res.setStatusCode(200);
        return res;
    }
}

YourTestClass: 
 
@isTest
private class CalloutClassTest {
     @isTest static 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 = CalloutClass.getInfoFromExternalService();
        
        // Verify response received contains fake values
        String contentType = res.getHeader('Content-Type');
        System.assert(contentType == 'application/json');
        String actualValue = res.getBody();
        String expectedValue = '{"example":"test"}';
        System.assertEquals(actualValue, expectedValue);
        System.assertEquals(200, res.getStatusCode());
    }
}

Here is the documentation for the full explanation: https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_classes_restful_http_testing_httpcalloutmock.htm

Hope this helps!
 
This was selected as the best answer
Naomi HarmonNaomi Harmon
Thank you Stas! So now I have to edit all my test classes with the callout mock? (Because now any of my test classes that inserted a test record are now failing due to those callout triggers.)
Naomi HarmonNaomi Harmon
I edited all my existing test classes to include a Test.setMock(HttpCalloutMock.class, new YourHttpCalloutMockImpl()); statement and fixed all the errors. Thanks!