How to mock an HTTP method of a REST message for ServiceNow ATF tests?
In case one wants to test a solution involving outbound REST integrations, like the one presented in 'Outbound REST Integrations', it is helpful to be able to mock the involved REST service.
How to do that?
Background
According to the ServiceNow API Reference / REST APIs / Automated Test Framework support, the Automated Test Framework (ATF) supports inbound - but not outbound - REST test steps.
I'd expect that outbound REST test steps are supported as well, with the ability to mock responses.
In the meantime I worked out how to mock a ServiceNow REST message HTTP method for ATF tests.
The solution (below) has a number of steps, but isn't complicated.
On the 'IPInfo' example presented in 'Outbound REST Integrations', the solution is like this:
Goal: Mock HTTP method 'GetIPInfo' of REST message 'IPInfo' (which normally calls 'https://ipinfo.io/${ipaddress}/${specific_field}').
Create a scripted REST API, for example in scope 'x_1234567_iplookup', with API ID 'mock_ipinfo_io_api'.
Create a scripted REST resource in it, to match the REST message 'IPInfo' to mock:
Active: false
Relative path: /{ipaddress}/{specific_field}
Requires authentication: false
Script:
(function process( /*RESTAPIRequest*/ request, /*RESTAPIResponse*/ response) {
response.setContentType('application/json; charset=utf-8');
response.setStatus(200);
var writer = response.getStreamWriter();
// Only the "city" field will be tested in this example.
let responseJson = {
"ip": "8.8.8.8",
"hostname": "dns.google",
"anycast": true,
// This is the value that will be tested:
"city": "Mock City",
"region": "California",
"country": "US",
"loc": "37.4056,-122.0775",
"org": "AS15169 Google LLC",
"postal": "94043",
"timezone": "America/Los_Angeles",
"readme": "https://ipinfo.io/missingauth"
};
writer.writeString(JSON.stringify(responseJson));
})(request, response);
Create a test:
Enable parameterised testing: true
Exclusive parameter definitions:
Column Label | Column Name | Type | Reference | Reference Qual. Condition |
---|---|---|---|---|
Expected City | u_expected_city | String (Full UTF-8) | ||
Given HTTP Method | u_http_method | Reference | HTTP Method | |
Given Instance Name | u_instance_name | Reference | System Property | Name is instance_name |
Given IP Address | u_ip_address | String | ||
Given Mocking Path | u_given_mock_endpoint | String | ||
Given Mocking Scripted REST Resource | u_given_mocking_scripted_rest_resource | Reference | Scripted REST Resource |
Create a test run data set:
Given IP Address: 8.8.8.8
Given Instance Name: instance_name
Given Mocking Path: /api/x_1234567_iplookup/mock_ipinfo_io_api/${ipaddress}/${specific_field}
Given HTTP Method: GetIPInfo
Expected City: Mock City
Given Mocking Scripted REST Resource: Get given field by IP address
Create test steps:
Record Update
Notes: Activate the mocking service.
Assert type: Record successfully updated
Table: Scripted REST Resource [sys_ws_operation]
Record: (Parameters➛Given Mocking Scripted REST Resource)
Field values: Active := true
Record Update
Notes: Redirect HTTP method to mocking service.
Assert type: Record successfully updated
Table: HTTP Method [sys_rest_message_fn]
Record: (Parameters➛Given HTTP Method)
Field values: https://(Parameters➛Given Instance Name➛Value).service-now.com(Parameters➛Given Mocking Path)
Open a New Form
Table: IPAddressInfo
Set Field Values
Table: IPAddressInfo
Field values: IP Address := (Parameters➛Given IP Address)
Submit a Form
Record Query
Timeout: Seconds 15
Assert type: There is at least one record matching the query
Table: IPAddressInfo
Conditions:
'Sys ID' is (Step 5: Submit a Form➛Record)
'City' is (Parameters➛Expected City)
Mark mutually exclusive (!) tests:
Execute the test.
Should anyone wish to import and check out the solution above, it can be cloned from my GitHub repository.