Test the example flow MyAtmFlow with a flow
action calling the external service MyAtmExternalService by implementing the HttpCalloutMock interface. The interface provides a test response without
performing the callout to the external service endpoint. The sample Apex unit test performs
a mock test against the same HTTP callout mock implementation.
{
"swagger": "2.0",
"basePath": "/",
"info": {
"version": "1.0",
"title": "My ATM External Service Demo",
"description": "Demo ATM OpenAPI service for mock testing"
},
"paths": {
"/accounts/{accountId}": {
"get": {
"operationId": "getBalance",
"summary": "Get account balance",
"description": "Get the current account balance for the given account ID and pin",
"consumes": [
"text/plain"
],
"produces": [
"application/json"
],
"parameters": [{
"name": "accountId",
"in": "path",
"required": true,
"type": "string",
"description": "Account ID"
}, {
"name": "pin",
"in": "header",
"required": true,
"type": "integer",
"description": "Account holder's PIN"
}],
"responses": {
"200": {
"description": "The response when system finds an account with given name",
"schema": {
"required": [
"accountId",
"name",
"type",
"availableBal"
],
"type": "object",
"properties": {
"accountId": {
"type": "string",
"description": "Unique account ID"
},
"name": {
"type": "string",
"description": "Account name"
},
"type": {
"type": "string",
"description": "Account type",
"example": "Checking"
},
"availableBal": {
"type": "integer",
"description": "Available balance"
}
}
}
},
"401": {
"description": "Invalid authentication or invalid account"
}
}
}
}
}
}
MyAtmExternalService is registered with a Named
Credential MyAtmNamedCredential, has operation
getBalance with String accountId as path parameter and Integer pin as header parameter. Its output is a JSON data
structure with the account ID, account holder, balance, and account type.
The HTTP callout mock implementation reacts to an expected test request by responding with the appropriate HTTP response output:
global class MyAtmHttpCalloutMock implements HttpCalloutMock {
global HTTPResponse respond(HTTPRequest request) {
// Assert expected request test data
System.assertEquals('GET', request.getMethod());
System.assertEquals('callout:MyAtmNamedCredential/A123-456', request.getEndpoint());
System.assertEquals('1234', request.getHeader('pin'));
// Send response test data
HttpResponse response = new HttpResponse();
response.setHeader('Content-Type', 'application/json');
response.setBody('{"availableBal": 0, "name": "Account Holder", ' +
'"type": "Checking", "accountId": "A123-456"}');
response.setStatusCode(200);
return response;
}
}
The flow test class sets up the HTTP callout mock for the external service action it’s calling. It creates a flow interview with input parameter values to test, runs the flow interview, and then asserts the actual flow output parameters with expected test values:
@IsTest
public class MyAtmFlowTest {
@IsTest
static public void testMyAtmFlow() {
// Set HTTP callout mock to match flow's external service action invocation
Test.setMock(HttpCalloutMock.class, new MyAtmHttpCalloutMock());
// Set flow input variables and create the flow interview
Map<String, Object> inputVariables = new Map<String, Object>();
inputVariables.put('accountId', 'A123-456');
inputVariables.put('pin', 1234);
Flow.Interview myAtmFlow = Flow.Interview.createInterview('MyAtmFlow',
inputVariables);
// Start flow interview with set input variables
myAtmFlow.start();
// Assert flow output variables
ExternalService.MyAtmExternalService_getBalance_OUT_200 expected =
new ExternalService.MyAtmExternalService_getBalance_OUT_200();
expected.availableBal = 0;
expected.name = 'Account Holder';
expected.type = 'Checking';
expected.accountId = 'A123-456';
System.assertEquals(expected.toString(),
(String)myAtmFlow.getVariableValue('myFlowOutput'));
}
}
The Apex test class sets up the HTTP callout mock for the external service method it’s calling. It calls directly the external service in Apex with input parameter values to test and then asserts the actual output parameters with expected test values. This Apex test class illustrates how you can test an external service directly, for example, to assert an expected behavior for a registered service. Application code using external services in Apex can perform unit testing following the same pattern:
@IsTest
public class MyAtmApexTest {
@IsTest
static public void testMyAtmCallout() {
// Set HTTP callout mock
Test.setMock(HttpCalloutMock.class, new MyAtmHttpCalloutMock());
// Call with the expected mock accountId and pin
ExternalService.MyAtmExternalService myAtm =
new ExternalService.MyAtmExternalService();
ExternalService.MyAtmExternalService.getBalance_Request request =
new ExternalService.MyAtmExternalService.getBalance_Request();
request.accountId = 'A123-456';
request.pin = 1234;
ExternalService.MyAtmExternalService_getBalance_OUT_200 actual =
myAtm.getBalance(request).Code200;
// Assert the response variables
ExternalService.MyAtmExternalService_getBalance_OUT_200 expected =
new ExternalService.MyAtmExternalService_getBalance_OUT_200();
expected.availableBal = 0;
expected.name = 'Account Holder';
expected.z0type = 'Checking';
expected.accountId = 'A123-456';
System.assertEquals(expected.toString(), actual.toString());
}
}