[SalesForce] Suggestions for Unit Tests on an APEX Class that Calls a Web Service and Retrieves XML

I am attempting to write a series of unit tests on a 2300+ line APEX class. The gist of the class is that it makes a Rest Request and retrieves an XML object from a web service. The class then assigns nodes from the XML file to objects in the Account, Opportunity and other object tables.

At this time, we have 0% code coverage. What should be tested, what should not be tested (such as the web service call), and how can we assure satisfactory code coverage for this type of class?

After seeing this question put on hold as too broad, and working a bit with REST request and HTTP Callout mocks, I've come up with the following:

public with sharing class CalloutClass {
public static HttpResponse getInfoFromExternalService(){
    RestRequest req = new RestRequest(); 
    req.requestURI = URL.getSalesforceBaseUrl().toExternalForm() + '/services/apexrest/IFXLoadXML/TEST';
    req.setMethod ('POST');
    Http h = new Http();
    RestResponse res = h.send(req);
    return res;
}

}

The test now has an error stating that HttpRequest doesn't have requestURI. So, I need to essentially make this mock a Rest request instead of an HttpRequest. Is that correct? If so, please help with any example code available to accomplish this callout mock within a test class. Thanks, and apologies for the broad initial question.

Best Answer

Your logic should be tested completely... for webservice calls there are mock callouts you can make to test out your logic. Salesforce HttpCalloutMock Doc

Pretty much your mock method will have your preloaded response since test cases cannot make callouts, this way your apex logic can run as though it is making a callout.

Your http mock callout will look like such.

global class YourHttpCalloutMockImpl implements HttpCalloutMock {
    global HTTPResponse respond(HTTPRequest req) {
        // Create a fake response.
        // Set response values, and 
        // return response.
    }
}

and your test classes will know what callout to use by providing it with the class

Test.setMock(HttpCalloutMock.class, new YourHttpCalloutMockImpl());

Working example provided by salesforce within the doc is as follows:

HTTP CALLOUT MOCK

@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://api.salesforce.com/foo/bar', req.getEndpoint());
        System.assertEquals('GET', req.getMethod());

        // Create a fake response
        HttpResponse res = new HttpResponse();
        res.setHeader('Content-Type', 'application/json');
        res.setBody('{"foo":"bar"}');
        res.setStatusCode(200);
        return res;
    }
}

ORIGINAL CALLOUT METHOD

public class CalloutClass {
    public static HttpResponse getInfoFromExternalService() {
        HttpRequest req = new HttpRequest();
        req.setEndpoint('http://api.salesforce.com/foo/bar');
        req.setMethod('GET');
        Http h = new Http();
        HttpResponse res = h.send(req);
        return res;
    }
}

TEST CASE

@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 = '{"foo":"bar"}';
        System.assertEquals(actualValue, expectedValue);
        System.assertEquals(200, res.getStatusCode());
    }
}
Related Topic