Vladimir Dyuzhev, author of MockMotor

Vladimir Dyuzhev
MockMotor Creator

How to Record and Mock REST Traffic with MockMotor

When recording a REST call, MockMotor automatically finds parameters in the request URL.

Tweet This

REST traffic is not very different from HTTP traffic. This is not a surprise since REST is HTTP.

However, in a REST service call, the URL can contain segments that are actual parameters. An account parameter that in HTTP is encoded as http://service?account=100500, in the pure REST would be http://service/account/100500.

This is not a dogma, and a REST service can use the query string, just as an HTTP service can have parameters in the URL.

MockMotor doesn't make a difference between REST and HTTP traffic when recording. However, it tries to find parameters in URL components and assign them reasonable names.

Let's see how MockMotor records REST.

Why Record at All?

Why do we need to record? Can't we just use the live service?

Well, there could be multiple very good reasons.

  • We may want to stay within the free account requests quota.
  • We may need to test special cases, such as errors or slow responses.
  • We may alter some response data to adjust them for our scenarios.
  • We may want to have a stable set of accounts to reuse for regression testing.
  • We may want to run load tests.

The Goal: Record a REST Service

Let's record a live REST service.

Our recording should:

  • Intercept calls with parameters, including those in URL components
  • Forward these calls to the live backend
  • Record the responses as mocks
  • Configure those mocks to match the original requests

The Backend: US National Library of Medicine's RxNorm

RxNorm is a service for medical applications. It allows for obtaining tonnes of special information about medications presented on the US market. See for yourself.

For us, however, it has two useful properties:

  • It's free to call
  • Its request URLs contain parameters

A typical request looks like this:

https://rxnav.nlm.nih.gov/REST/rxcui/18600/allProperties.json?prop=all

Here 18600 is a RxCUI code for azatadine.

The response is a rather large JSON payload that contains all properties for this substance:

{"propConceptGroup": {"propConcept": [
    {
        "propCategory": "ATTRIBUTES",
        "propName": "TTY",
        "propValue": "IN"
    },
    {
        "propCategory": "ATTRIBUTES",
        "propName": "PRESCRIBABLE",
        "propValue": "Y"
    },
    {
        "propCategory": "CODES",
        "propName": "RxCUI",
        "propValue": "18600"
    },
    {
        "propCategory": "CODES",
        "propName": "NUI",
        "propValue": "N0000007088"
    },
...

Needless to say, the responses for /rxcui/18600/ and say /rxcui/7052/ (morphine) are very different. When recording mocks for this backend, we should create two different mocks - one matching 18600 and another matching 7052 (and then maybe dozens more matching other substances used in test runs).

Let's proceed.

Create a Service

First, let's create a test service that is going to mock RxNorm.

Nothing special is required. We assign it a relative URL of /RxNorm, and the full mock service URL is seen at the top of the page:

Create a Forward Response

Now its time to add a forwarding/recording response to the service.

  • It should match GET HTTP operation (all RxNorm calls use GET)
  • It should match any relative URL.
  • It should have the RxNorm service's URL base set in the Forward field - https://rxnav.nlm.nih.gov/REST/
  • It should have Recording enabled.

Below is the forward response. Not important properties are hidden.

In the responses list, the forwarding response looks like this:

Now, when we call this mock service, the forwarding response calls the live backend with our payload and records the response as a mock.

Record the Responses

Let's run a few test cases that get information for RxCUIs via our mock service.

Here is a call for Azatadine information:

http://127.0.0.1:20072/RxNorm/rxcui/18600/allProperties.json?prop=all

Since we do not have any local mocks yet, the request is handled by the forwarding mock response. It sends the request to the actual RxNorm backend. When the backend responds, MockMotor records the response properties as a new mock.

MockMotor sees that the request payload is not XML (in fact, the payload is missing because it is an HTTP GET) and decides it must be an HTTP/REST call.

For the HTTP part, it finds the prop=all HTTP query parameter and adds it to the match script as http.parameter.prop=="all".

For the REST part, MockMotor analyzes the URL, trying to find any sequence that looks like a name/value pair. It is not always easy, but for our URL, the /rxcui/18600 sequence is very likely a key and a value. MockMotor hence defines the relative URL as

rxcui/{rxcui}/allProperties.json

so the REST parameter rxcui gets its value from the URL component.

Lastly, MockMotor adds a condition rest.parameter.rxcui=="18600" to the matching script so that only requests for 18600 match this new response.

Let's execute two more requests:

Morphine:

http://127.0.0.1:20072/RxNorm/rxcui/7052/allProperties.json?prop=all

Zithromax 500 MG Injection:

http://127.0.0.1:20072/RxNorm/rxcui/1668240/allProperties.json?prop=all

Review the Recorded Responses

Let's take a look at the service's responses again:

You can see that the forward mock has created three mock responses.

Each of the recorded mocks has its own version of the match script, containing its own specific values of RxCUI value, e.g.:

http.parameters.prop=="all" && rest.parameters.rxcui=="18600"

In addition to the response payload and the match script, MockMotor recorded:

  • HTTP operation GET
  • Relative URL rxcui/{rxcui}/allProperties.json
  • HTTP status 200
  • Content-Type application/json
  • The response payload for this RxCUI
  • Response time

Test the Recorded Mocks

The newly recorded mocks are now handling the matching requests. If we repeat the same requests again, we can see that the RxNorm backend isn't called.

Once we collect all the responses we need for our test scenarios, we do not need to call the actual backend at all. When the backend has to be leased to a team, this can mean large savings.

You can see the complete service on the demo MockMotor instance.

Please Share

Was this post useful? Then please share! Tweet This