I've found I've had to add something like this in my actual Class methods to switch my testMock if I'm running a test.
public String getActivityFile() {
if(test.isRunningTest) {
Test.setMock(WebServiceMock.clas, new WebserviceNumber2Mock());
}
return new WebserviceNumber2().getActivityFile();
}
Update 2018-05-22
Extending this idea, it's a pain to deal with circular references when referencing a Test class in a Production class. However, you can references a Test Class Type
without causing a direct reference to another class. As of today (API 42.0), Types are not compiled when saving Apex. So you can do something like the following:
public abstract class SoapApi {
public interface Request {
Type getType();
Type getResponseType();
Type getMockResponseType();
String getSoapAction();
String getRequestNamespace();
String getResponseNamespace();
String getResponseName();
}
public abstract class MockResponse implements WebServiceMock {
// Abstract
public abstract Object getResponse(Request request);
protected Object response;
// WebServiceMock
public void doInvoke(
Object stub,
Object request,
Map<String, Object> response,
String endpoint,
String soapAction,
String requestName,
String responseNamespace,
String responseName,
String responseType
) {
if(!(request instanceof Request)) {
new InvalidMockRequestException(System.Label.SoapApi_InvalidMockRequestException); // 'Requestable must implement SoapApi.Requestable'
}
this.response = this.getResponse((Request) request);
response.put('response_x', this.response);
}
}
// Abstract
public abstract String getEndpoint();
// Instance
public Object send(SoapApi.Request request) {
if(request == null) {
throw new NullRequestException(System.Label.SoapApi_NullRequestException); // 'Request cannot be null'
}
if(request.getType() == null) {
throw new NullRequestTypeException(System.Label.SoapApi_NullRequestTypeException); // 'Request\'s Type cannot be null'
}
if(Test.isRunningTest()) {
Object response = request.getMockResponseType() == null ? null : request.getMockResponseType().newInstance();
if(!(response instanceof MockResponse)) {
throw new InvalidMockResponseException(System.Label.SoapApi_InvalidMockResponseException); // 'Request\'s Mock Response Type must extend SoapApi.MockResponse'
}
Test.setMock(WebServiceMock.class, response);
}
// Invoke WebServiceCallout
Map<String, Object> responses = new Map<String, Object> {
'response_x' => null
};
try {
WebServiceCallout.invoke(
this,
request,
responses,
new String[] {
this.getEndpoint(),
request.getSoapAction(),
request.getRequestNamespace(),
request.getRequestName(),
request.getResponseNamespace(),
request.getResponseName(),
request.getResponseType().getName()
}
);
} catch(Exception e) {
// Can do debugging here else remove the Try/Catach
throw e;
}
return responses.get('response_x');
}
}
public with sharing class ThirdPartyData {
public with sharing class LocationRequest implements SoapApi.Request {
public String address;
@TestVisible String[] address_type_info = new String[] {/* ... */};
@TestVisible String[] apex_schema_type_info = new String[] {/*...*/};
@TestVisible String[] field_order_type_info = new String[] {
'address'
};
// SoapApi.Request
public Type getType() {
return ThirdPartyData.LocationRequest.class;
}
public Type getResponseType() {
return return ThirdPartyData.LocationResponse.class;
}
public Type getMockResponseType() {
return return ThirdPartyDataMock.LocationResponse.class;
}
public String getSoapAction() {
return String.join(
new String[] {
'https://api.example.com',
'ThirdPartData',
'getLocation'
},
'/'
);
}
public String getRequestNamespace() {
return 'ThirdPartyData';
}
public String getResponseNamespace() {
return 'ThirdPartyData';
}
public String getResponseName() {
return 'LocationResponse';
}
}
public with sharing class LocationResponse {
public String address, city, state, postal;
@TestVisible String[] address_type_info = new String[] {/* ... */};
@TestVisible String[] city_type_info = new String[] {/* ... */};
@TestVisible String[] state_type_info = new String[] {/* ... */};
@TestVisible String[] postal_type_info = new String[] {/* ... */};
@TestVisible String[] apex_schema_type_info = new String[] { /*...*/};
@TestVisible String[] field_order_type_info = new String[] {
'address',
'city',
'state',
'postal'
};
}
// Instance
public with sharing class Api extends SoapApi {
public Integer timeout_x = 60000; // Milliseconds
public String[] ns_map_type_info = new String[] {
'https://api.example.com', 'ThirdPartData',
};
public Map<String, String> inputHttpHeaders_x;
public Api() {
super();
}
// SoapApi
public override String getEndpoint() {
return 'callout:packagenamepace__ThirdPartData/Api.svc';
}
public LocationResponse getLocation(String address) {
LocationRequest request = new LocationRequest();
{
request.address = address;
}
return (LocationResponse) this.send(request);
}
}
}
@IsTest
public with sharing class ThirdPartyDataMock {
public with sharing class InvalidMockRequestException extends Exception {}
public with sharing class LocationResponse extends SoapApi.MockResponse {
public override Object getResponse(SoapiApi.Request request) {
if(!(request instanceof ThirdPartyData.LocationRequest)) {
throw new InvalidMockRequestException(String.format(
System.Label.ThirdPartyDataMock_InvalidMockRequestException, // '{0} only supports {1}'
new String[] {
ThirdPartyDataMock.LocationResponse.class.getName(),
ThirdPartyData.LocationRequest.class.getName()
}
));
}
ThirdPartyData.LocationRequest locationRequest = (ThirdPartyData.LocationRequest) request;
ThirdPartyData.LocationResponse response = new ThirdPartyData.LocationResponse();
{
response.address = address;
response.city = 'Anytown';
response.state = 'MI';
response.postal = '49000';
}
return response;
}
}
}