SoatDev IT Consulting
SoatDev IT Consulting
  • About us
  • Expertise
  • Services
  • How it works
  • Contact Us
  • News
  • June 22, 2023
  • Rss Fetcher

Creating your stateful sandbox with WireMock

Photo by Markus Spiske on Unsplash

Wiremock is a great tool to test your application against a real web service with predefined stubs. It allows us to write integration tests that do not stop at a rest client mock but do network communication, simulating different responses with limited effort.

But WireMock does not stop there: it also provides a standalone version that allows one to spin up a server with predefined stubs and thus is a fully functional web service.

For using WireMock as a sandbox, this article will give a brief overview of the following:

  • Creating plain stubs
  • Using dynamic templates for building responses
  • Using scenarios to change responses based on previous requests
  • Transporting state from a previous request to the next one

Why Create a Sandbox

When developing a web service with other external services, it is usually not desired to interact with these external services in the developing phase. Imagine doing branch deployments or having a staging environment and running manual and end-to-end tests. You might not want this to cause additional costs, have unwanted side effects — or take long.

One solution to this is a sandbox: an isolated environment for testing purposes. WireMock can be used to create one. I prepared a sample application encapsulated in a Spring Boot application and full examples for everything mentioned here. The standalone version would also work for many scenarios, but for one use case, you need a special extension :-).

GitHub – dirkbolte/medium-wiremock-sandbox

Plain Stubs

This use case is probably used the most often, especially in integration tests: Match a request and create a stub response. All requests will get the same answer.

{
"request": {
"method": "GET",
"url": "/plain",
"headers": {
"accept": {
"contains": "json"
}
}
},
"response": {
"status": 200,
"headers": {
"Content-Type": "application/json"
},
"jsonBody": {
"id": "oghrhc8uh0q0b5vmytxd7zvxm3ydkm5j",
"createdAt": "2023-06-21T12:35:48Z",
"updatedAt": "2023-06-21T12:35:48Z"
}
}
}

You can have multiple answers prepared and differentiate themes based on request parameters. Adding variations to it is cumbersome and might not be possible as you don’t want to leak sandbox information into your application.

Response Templating

You can add dynamic elements to your requests using response templating. For that, the ResponseTemplateTransformer extension has to be registered:

var server = new WireMockServer(options()
.port(8080)
.extensions(new ResponseTemplateTransformer(true));

Now, you can use handlebars templates in your responses to, e.g., calculate new values or use parts of the request part or request body:

{
"request": {
"method": "POST",
"urlPattern": "/template/jsonbody",
"headers": {
"accept": {
"contains": "json"
},
"content-type": {
"contains": "json"
}
}
},
"response": {
"status": 200,
"headers": {
"Content-Type": "application/json"
},
"jsonBody": {
"id": "{{randomValue length=32 type='ALPHANUMERIC' uppercase=false}}",
"firstKey": "{{jsonPath request.body '$.firstKey'}}",
"createdAt": "{{now}}",
"updatedAt": "{{now}}"
}
}
}

The response would look like this:

{
"id": "spkgecneggjwqguj5mfchc7n3lznzcmf",
"firstKey": "firstValue",
"createdAt": "2023-06-21T13:52:55Z",
"updatedAt": "2023-06-21T13:52:55Z"
}

Attention: In case you want to use a complete JSON object of the initial request, you need to:

  • use body instead of jsonBody and thus have to write the whole JSON in one line
  • use {{{jsonPath request.body ‘$.firstObject’}}} instead of “{{jsonPath request.body ‘$.firstObject’}}” (so, no quotation marks or triple curly braces)

Here’s an example:

"response": {
"body": "{"firstObject": {{{jsonPath request.body '$.firstObject'}}}}"
}

With this, you add some dynamics to your sandbox, but the behavior doesn’t change in between calls: the first GET to an API would behave the same way as the second GET.

Scenarios

WireMock scenarios introduce a state for requests. Scenarios have a name and a state (initially, Started ). For each mapping, you can define the scenario they belong to, the state they are associated with, and optionally a new state for the scenario once the request is processed.

Here’s an example:

  1. For scenario CRUD , the stubs are in state Started
  2. GET for state Started will return the HTTP status 404
  3. POST will return a JSON body and change the scenario state to Created
  4. GET for state Started will return the HTTP status 201 along with a hardcoded body
  5. DELETE will return the HTTP status 204 and change the scenario state to Started again
  6. GET for state Started will return the HTTP status 404 again

Here’s a shortened example:

{
"mappings": [
{
"scenarioName": "CRUD",
"requiredScenarioState": "Started",
"request": {
"method": "GET"
},
"response": {
"status": 404
}
},
{
"scenarioName": "CRUD",
"requiredScenarioState": "Started",
"newScenarioState": "Created",
"request": {
"method": "POST",
"urlPattern": "/scenario",
},
"response": {
"status": 201,
"jsonBody": {}
}
},
{
"scenarioName": "CRUD",
"requiredScenarioState": "Created",
"request": {
"method": "GET"
},
"response": {
"status": 200,
"jsonBody": {}
}
},
{
"scenarioName": "CRUD",
"requiredScenarioState": "Created",
"newScenarioState": "Started",
"request": {
"method": "DELETE",
},
"response": {
"status": 204
}
}
]
}

Scenarios introduce some states, but we cannot transfer anything from a previous request to the next. We can still apply response templating but can only use the data of the current request.

State

There’s no built-in way to transport state in between stubs. Stubs are relatively isolated. Luckily, WireMock allows it to be extended. A sample extension for transporting state in between requests is available on GitHub. The sample extension also supports templates in their definitions.

GitHub – dirkbolte/wiremock-extension-state

We register an extension for postServeActions to record a state as well as response templating helper to retrieve a previous state:

var stateRecordingAction = new StateRecordingAction();
var server = new WireMockServer(options()
.port(8080)
.extensions(
stateRecordingAction,
new ResponseTemplateTransformer(true, "state", new StateHelper(stateRecordingAction))
);

To record a state, define a postServeAction to store data in association with a context, retrieving data from the current request and response:

{
"response": {
"status": 201,
"headers": {
"Content-Type": "application/json"
},
"jsonBody": {
"id": "{{randomValue length=32 type='ALPHANUMERIC' uppercase=false}}",
"createdAt": "{{now}}",
"updatedAt": "{{now}}"
}
},
"postServeActions": [
{
"name": "recordState",
"parameters": {
"context": "{{jsonPath response.body '$.id'}}",
"state": {
"firstKey": "{{jsonPath request.body '$.firstKey'}}",
"createdAt": "{{jsonPath response.body '$.createdAt'}}",
"updatedAt": "{{jsonPath response.body '$.updatedAt'}}"
}
}
}
]
}

The data can now be retrieved in the GET request based on the context provided in the URL (so, e.g., the ID of the entity that was created previously):

{
"request": {
"method": "GET",
"urlPattern": "/[^/]+"
},
"response": {
"status": 200,
"headers": {
"Content-Type": "application/json"
},
"jsonBody": {
"id": "{{request.pathSegments.[1]}}",
"firstKey": "{{state context=request.pathSegments.[0] property='firstKey'}}",
"createdAt": "{{state context=request.pathSegments.[0] property='createdAt'}}",
"updatedAt": "{{state context=request.pathSegments.[0] property='updatedAt'}}"
}
}
}

Conclusion

With WireMock, you can create a powerful sandbox for testing your application. You can already cover many scenarios with stubs, response templating, and scenarios. Its extension mechanism even allows it to cover more complex scenarios like transferring states depending on a context.

Sandbox creation requires minimal code and can be easily adapted to many third-party backend and their behavior.

Resources

  • Wiremock documentation
  • Sample WireMock extension for state
  • Sample WireMock sandbox


More Than Just Stubs was originally published in Better Programming on Medium, where people are continuing the conversation by highlighting and responding to this story.

Previous Post
Next Post

Recent Posts

  • An investor makes a case for funding sex, drugs and other socially taboo products
  • Noventiq & AWS Partners with MoIAT to Accelerate Industrial Digital Transformation
  • How to Kill Floundering Experiments and Drive an AI Learning Culture
  • BankservAfrica, Change Logic Introduce Framework to Mitigate Interbank Risks
  • Why is Compliance the Key to Africa’s Crypto Future

Categories

  • Industry News
  • Programming
  • RSS Fetched Articles
  • Uncategorized

Archives

  • June 2025
  • May 2025
  • April 2025
  • February 2025
  • January 2025
  • December 2024
  • November 2024
  • October 2024
  • September 2024
  • August 2024
  • July 2024
  • June 2024
  • May 2024
  • April 2024
  • March 2024
  • February 2024
  • January 2024
  • December 2023
  • November 2023
  • October 2023
  • September 2023
  • August 2023
  • July 2023
  • June 2023
  • May 2023
  • April 2023

Tap into the power of Microservices, MVC Architecture, Cloud, Containers, UML, and Scrum methodologies to bolster your project planning, execution, and application development processes.

Solutions

  • IT Consultation
  • Agile Transformation
  • Software Development
  • DevOps & CI/CD

Regions Covered

  • Montreal
  • New York
  • Paris
  • Mauritius
  • Abidjan
  • Dakar

Subscribe to Newsletter

Join our monthly newsletter subscribers to get the latest news and insights.

© Copyright 2023. All Rights Reserved by Soatdev IT Consulting Inc.