[SalesForce] Unit testing with SOAP and REST callouts

My project assumes quite big integration with external webservices.
Unfortunately first major service is SOAP and second is REST.

Problem is that there are getting more and more places in the code where for example SOAP callout needs some value from different REST callout.
Putting this methods inside one wrapper is impossible for me to test since Apex is allowing only to mock one type of callout at the time (either REST or SOAP).

Question: How to create unit test with mocks for both callouts to achieve 100% code coverage of the wrapper method?

Best Answer

Without getting into specifics ( partially because there aren't any, and also because I've only dabbled in this area ) you want to leverage a pattern called Dependency Injection.

Essentially, the idea is to separate your code & calls so that you can pass the result of a call into a helper class. This lets you create mock results in your test class, and test specific parts of a larger system without needing to make a large number of calls. A very simple example is below.

Response response = Caller.Call(); // Calls rest api 

Handler.Handle(response); // Handler calls soap api

// In the test, you can create a "mock" object of a response, and pass that to your handler. 

Response testResponse = new Response( ... ); // Doesnt call rest api, but has a identical response 

Handler.Handle(testResponse); // calls soap api 

You might have done something close to this - maybe you have a test which has some json in a certain format, which your code is supposed to get from a webservice. Instead of calling the service, you fake a call, and return this explicit json instead. The idea here is exactly the same!

You'll probably need more than one wrapper, and an overhaul of your code in order to make it testable. This is something thats best designed from the start with testing in mind (which is where test-driven development comes from).

Specifically, on the platform, the Stub API is provided to help mock methods. This would be a good place to start looking & designing around.


Heres a better example of setting up a mock (without the stub api):

public void MakeCall(Caller c) {
    Response r = c.Call(); // rest

    Handler.Handle(r); 
}

// Test class 

public interface Caller {
    public Response Call(); 
}

public class MyCaller inherits Caller {
    public Response Call() {
        return RestApi.Call(); // Valid call out 
    }
}

public class MockCaller inherits Caller {
    public Response Call() {
        return new Response( ... ); // pre-set result - can vary result for mult. tests 
    }
}