Building Event Driven systems is great, but not all systems are Event Driven. Communication with those systems can be via HTTP and those systems may not be able to respond quickly to a request, taking up to minutes to serve a response.

Are there tools to mock such a situation to be used for testing?

Context

When a system takes up to minutes to respond to a request, it is possible to first respond technically to the request and later respond functionally. The other system can POST the functional response. Then the response is asynchronously served.

WireMock to the rescue

WireMock has a PostServeAction, but the documentation on it is limited, which made me write this blog, so everyone can happily use this to their extend.

You can add behaviour that runs after a response has been completely served by extending PostServeAction and registering as an extension.
— WireMock
http://wiremock.org/docs/

Using WireMock’s PostServeAction and extending WireMock’s Webhooks extension makes it possible to return the functional response.

How To

First, let’s extend WireMock’s Webhooks extension and make it known to WireMock.

In the request a messageId is present and the response has a replyToMessageId, so the response can be correlated to the request. This means the response needs to contain the request’s messageId.

Define a Definition, containing a ResponseModel and a serverPort. The serverPort is used to let the mock know on which port the server expecting the response, runs.

public class ResponseDefinition {
    ResponseModel update;
    Integer serverPort;

    public static ResponseDefinition definition() {
        return new ResponseDefinition();
    }
}

The ResponseWebhook extracts the messageId from the request, extracts the definition, the ResponseModel, and populates the replyToMessageId with the extracted messageId from the request. Next we wrap this all in a new Webhooks instance and call super.doAction(). This will POST the ResponseModel to the configured endpoint.

public class ResponseWebhook extends Webhooks {

    @Override
    public String getName() {
        return "ResponseWebhook";
    }

    @Override
    public void doAction(ServeEvent serveEvent, Admin admin, Parameters parameters) {
        var messageId = Json.node(serveEvent.getRequest().getBodyAsString()).get("messageId").asText();

        var definition = parameters.as(ResponseDefinition.class);
        var transformedUpdate = definition.getUpdate().withReplyToMessageId(messageId);
        var webhookParameters = Webhooks.webhook()
            .withMethod(RequestMethod.POST)
            .withHeader("Content-Type", MediaType.APPLICATION_JSON_VALUE)
            .withUrl("http://localhost:"+definition.getLocalServerPort()+"/i-want-the-response")
            .withBody(Json.write(transformedUpdate));

        super.doAction(serveEvent, admin, Parameters.of(webhookParameters));
    }
}

The next step is to register the extension.

var wireMockServer = new WireMockServer(
    options()
        .dynamicPort()
        .extensions(
            ResponseWebhook.class
        )
);
wireMockServer.start();

At last create a mock using the ResponseWebhook extension.

givenThat(post(urlPathEqualTo("/other-domain"))
    .willReturn(aResponse().withStatus(202))
    .withPostServeAction(
        "ResponseWebhook",
        ResponseWebhook.definition()
            .withLocalServerPort(localServerPort)
            .withUpdate(new ResponseModel())
    );

The code above returns a HTTP-202 (ACCEPTED), the technical response, and will execute the PostServeAction. The PostServeAction will send the functional response to an endpoint.

shadow-left