Mockintosh: Multiple Responses and Datasets

In this part we will talk about the multiple responses and datasets in Mockintosh. ​

Multiple Responses

Instead of being a plain string or a JSON object, the response field in an endpoint can also be a list of responses.

services:
    - port: 8081
      endpoints:
          - path: "/example"
            response:
                - "response 1"
                - "response 2"
                - "response 3"

We call this "multiple responses". It enables you to simulate interesting scenarios like; an endpoint returns different responses or a sequence of responses for multiple requests. ​

import httpx

def do_request() -> int:
    resp = httpx.get('http://localhost:8081/example')
    return resp.status_code

def test_example():
    assert do_request() == 202
    assert do_request() == 202
    assert do_request() == 202
    assert do_request() == 503

Let's imagine that you have a microservice that can handle a finite amount of background tasks and you can POST tasks to that service via an endpoint. These tasks are some time critical tasks, like a stock exchange order. The microservice is overloaded when there are more than 3 tasks are running simultaneously. The endpoint that you use for ordering tasks returns 202 - Accepted if it's not overloaded otherwise it returns 503 - Server is busy. ​ How would you simulate such a scenario without having control over the API, or spending a huge effort to clone that API just to test a simple case like this deterministically? That's where Mockintosh comes in. With a Mockintosh configuration like this, you can easily replicate the scenario without wasting your precious time.

services:
    - port: 8081
      endpoints:
          -path: "/example"
          multiResponsesLooped: false ## Looping disabled
          response:
              - status: 202
                headers:
                    Content-Type: "application/json; charset=UTF-8"
                body: '{"status": 200, "message": "Accepted"}'
              - status: 202
                headers:
                    Content-Type: "application/json; charset=UTF-8"
                body: '{"status": 200, "message": "Accepted"}'
              - status: 202
                headers:
                    Content-Type: "application/json; charset=UTF-8"
                body: '{"status": 200, "message": "Accepted"}'
              - status: 503
                headers:
                    Content-Type: "application/json; charset=UTF-8"
                body: '{"status": 503, "message": "Server is busy"}'

​ This endpoint responds to the first 3 requests with 202, and then responds to the fourth request with 503. Notice how looping is disabled by setting multiResponsesLooped field to false. This makes the endpoint respond with 410 - Gone after the fourth request. ​ Note that responses are looped forever if the multiResponsesLooped field is set to true or is not supplied. ​

Tagged Responses

Imagine the previous scenario again, but this time you want to have the control to set the state of microservice's busyness. ​ To achieve this, Mocktintosh has "tags". Using tags you can change the state of a looped response list to make it only respond with a subset of the response list. ​ You can set tags through the Mockintosh command-line interface: $ mockintosh 03.yaml --enable-tags='accepted'] or by requesting to the management API: $ curl -X POST http://localhost:8080/tag --data 'accepted'

Datasets

Datasets in Mockintosh, similar to "multiple responses", are a list of variables that are injected into templating in the response field. This is useful when testing a scenario like a series of sequential responses.

services:
    - port: 8081
      endpoints:
          - path: "/example"
            dataset:
                - var: "value 1"
                - var: "value 2"
                - var: "value 3"
            response: "var: {{var}}"

​ For example, there is an API endpoint that sometimes returns an integer or a floating point number, and other times returns a string for a JSON field. Datasets in Mockintosh is the solution to replicate such cases deterministically.

import httpx

def do_request() -> str:
    resp = httpx.get('http://localhost:8081/example')
    data = resp.json()
    var = data['var']
    if isinstance(var, int):
        return 'integer'
    elif isinstance(var, float):
        return 'float'
    if is instance(var, str):
        return 'string'
    else:
        raise Exception()

def test_example():
    assert do_request() == 'integer'
    assert do_request() == 'float'
    assert do_request() == 'string'

​ To replicate this case, you define a dataset with three elements: 5, 3.14, and the "hello world" string. Mockintosh will iterate through this dataset for each request.

services:
    - port: 8081
      endpoints:
          - path: "/example"
            dataset:
                - var: 5
                - var: 3.14
                - var: '"hello world"'
            response:
                headers:
                    Content-Type: "application/json; charset=UTF-8"
                body: '{"var": {{var}}}'

Tagged Datasets

Similar to "tagged responses" using the tag field in datasets is also possible. ​ You can set the state of this dataset and make the endpoint to always return a string after a certain point. ​

Support

You can view these examples in action in this video, and learn more at Mockintosh and UP9. Join our community Slack at up9.slack.com.