mbtest icon indicating copy to clipboard operation
mbtest copied to clipboard

Allow retrieval of proxied request responses via the API using the replayable option

Open garry-jeromson opened this issue 4 years ago • 7 comments

The record and replay functionality of Mountebank is really useful in that it allows creation of imposters based on real requests and responses - it's a big workflow win. Mountebank offers this functionality natively (see http://www.mbtest.org/docs/api/overview#get-imposter), but it would be nice if this library wrapped the API calls for usability. I'm new to the codebase, but on first glance it seems like it'd be fairly easy to add this as a new method to the MountebankServerclass.

garry-jeromson avatar May 11 '20 08:05 garry-jeromson

Cherry-on-the-cake functionality would be then being able to output the replayable response to a JSON imposter file.

garry-jeromson avatar May 11 '20 08:05 garry-jeromson

As an illustration of the functionality that would be nice to integrate into the library, the flow would be something like this (our current patched-together solution):

import json

import requests
from hamcrest import assert_that
from mbtest.imposters import Imposter, Proxy
from mbtest.matchers import had_request
from mbtest.server import MountebankServer

UPSTREAM_SERVICE_SERVER_URL = "http://worldtimeapi.org"
UPSTREAM_SERVICE_ENDPOINT_PATH = "/api/ip"
IMPOSTER_PORT = 35000
IMPOSTER_NAME = "World Time API"


def test_record_and_replay():
    """
    Proxy and record an outgoing request, in order to save the response to use in integration test runs.

    See http://www.mbtest.org/docs/api/overview#get-imposter.
    """
    running_server = MountebankServer(host="mountebank", port=2525)
    proxy_imposter = Imposter(Proxy(to=UPSTREAM_SERVICE_SERVER_URL), port=IMPOSTER_PORT, name=IMPOSTER_NAME)
    with running_server([proxy_imposter]) as server:
        #  Workaround so that imposter host matches server in docker-compose setup
        url = proxy_imposter.url
        url.host = "mountebank"

        # Perform the request we want to proxy and record
        requests.get(f"{url}{UPSTREAM_SERVICE_ENDPOINT_PATH}")
        assert_that(server, had_request(path=f"{UPSTREAM_SERVICE_ENDPOINT_PATH}", method="GET"))

        #  Get the request/response data from Mountebank
        imposter_data = requests.get(f"{server.server_url}/{proxy_imposter.port}?replayable=true&removeProxies=true")
        replayable_operation = json.loads(imposter_data.content)

        # Save the file here, with some options regarding content.
        with open("some_stub_or_imposter.json", "w") as output_file:
            json.dump(replayable_operation, output_file)

garry-jeromson avatar May 11 '20 09:05 garry-jeromson

Yup, this looks like a great idea to me. Let's get the other PR sorted first, and released (since it's really a bugfix!) and then add this.

brunns avatar May 11 '20 09:05 brunns

Though a method on MountebankServer should probably return Impostor objects rather than raw JSON. You should be able to use the to_structure() method to turn them back into JSON.

brunns avatar May 11 '20 09:05 brunns

Do you want to take a run at this, @garry-jeromson, or shall I?

brunns avatar May 12 '20 10:05 brunns

D'you fancy taking it on? My first target is a Dockerised development setup (for lazy folks like myself), working on a pull request at the mo. 🤓

garry-jeromson avatar May 15 '20 08:05 garry-jeromson

Oh, that would be welcome, thank you.

brunns avatar May 15 '20 08:05 brunns