WireMock : Mocking a REST API with Practical Use Cases

The most common requirement when integrating a third-party RESTful API into your app is to have a mock of this API for testing. Every well-built system should support passing a different service endpoint depending on the context. In non-production environments, we can use a mock of the third-party API, while in production we use the actual service.


There are different approaches to building a mock. If the API comes with an OpenAPI specification, we could generate a skeleton web service from it. We would then use a back-end web framework to implement its actual logic, connect it to a database, or simply return static content. Typically, we don’t want to use every part of an API, nor do we want to over-engineer and build the whole thing ourselves.


WireMock offers a generous trade-off between the amount of work required and the usability of the mocked service. It excels in its simplicity of use and setup. Once implemented, it can be easily tweaked or changed in case of an API update. It can even be used without a complete specification by simply mapping requests to responses, which is beneficial when mocking an API that is not yet in production.


WireMock is framework-agnostic and can be used standalone with plain Java or easily integrated with frameworks like Spring Boot. While the original WireMock is a Java library, there are ports for other languages, such as WireMock.Net for C#, which are separate implementations. We won’t discuss these in detail, as we will focus on Java code.

Use Case 1 : WireMock Setup

This section demonstrates how to quickly set up WireMock using Maven.

Add WireMock Dependency: Add the following to your pom.xml:


org.wiremock
wiremock-standalone
3.13.2

Basic WireMock Configuration: Set up the server port, static files folder, and console notifier

public class WireMockApplication {

public static final String filesClasspath = “wiremock”;
public static final boolean wireMockVerbose = true;

public static void main(String[] args) {
WireMockServer wm = new WireMockServer(
wireMockConfig()
.port(8080)
.usingFilesUnderClasspath(filesClasspath)
.notifier(new ConsoleNotifier(wireMockVerbose)));
wm.start();
}
}

Folder structure:

resources/
└── wiremock/
└── mappings/
└── testMethod/
└── testMethod1.json
└── __files/
└── responses/
└── testMethod1-response.json

Mapping File Example:

//file named testMethod1.json
{
“request”: {
“method”: “GET”,
“urlPattern”: “/test-method”
},
“response”: {
“status”: 201,
“bodyFileName”: “responses/testMethod1-response.json”,
“headers”: {
“Content-Type”: “application/json”
}
}
}

Response File Example:

//file named testMethod1-response.json
{
“a”: “something”,
“b”: 123,
“c”: true
}

Start the application and access http://localhost:8080/test-method to see the mocked response.

Use Case 2 : Header-based Dynamic Mapping

In basic scenarios, mapping a request to a single static response file is often sufficient. However, for more complex logic, such as simulating different states of a process, a dynamic approach is needed. Here, we use WireMock’s Response Templating feature to generate responses based on a request header value.

Suppose we have an endpoint that returns the status of an event in a processing pipeline. The status could be “CREATED”, “IN_PROGRESS”, or “COMPLETED”. We want to simulate different pipeline states by changing the response based on an HTTP header.

We use a response template to select the response file dynamically, based on a defined X-Mock-Behaviour header.

//file named eventStatus.json
{
“request”: {
“method”: “GET”,
“urlPattern”: “/event-status”
},
“response”: {
“status”: 200,
“bodyFileName”: “responses/eventStatus-response_{{get-status request.headers.X-Mock-Behaviour}}.json”,
“transformers”: [“response-template”]
}
}

We will also specify separate response files for each status of an event we would like to mock.

//file named eventStatus-response_CREATED.json
{
“id”: “c7e2a1b4-8f3e-4b2a-9c1d-2e5f7a6b3c4d”,
“status”: “CREATED”
}

//file named eventStatus-response_IN_PROGRESS.json
{
“id”: “c7e2a1b4-8f3e-4b2a-9c1d-2e5f7a6b3c4d”,
“status”: “IN_PROGRESS”
}

//file named eventStatus-response_COMPLETED.json
{
“id”: “c7e2a1b4-8f3e-4b2a-9c1d-2e5f7a6b3c4d”,
“status”: “COMPLETED”
}

Since get-status is a custom function, we implement it as a WireMock extension:

package com.example.extensions;

import com.github.tomakehurst.wiremock.common.ListOrSingle;
import com.github.tomakehurst.wiremock.extension.TemplateHelperProviderExtension;
import wiremock.com.github.jknack.handlebars.Helper;

import java.util.Map;
import java.util.Optional;

public class StatusHelperExtension implements TemplateHelperProviderExtension {

public static final String EVENT_STATUS = “event-status:”;
public static final String DEFAULT_STATUS = “completed”;
public static final String HELPER_NAME = “get-status”;
public static final String EXTENSION_NAME = “event-status-helpers”;

@Override
public String getName() {
return EXTENSION_NAME;
}

@Override
public Map> provideTemplateHelpers() {
Helper> helper = (context, options) ->
Optional.ofNullable(context)
.map(ListOrSingle::getFirst)
.map(Object::toString)
.filter(s -> s.startsWith(EVENT_STATUS))
.map(s -> s.substring(EVENT_STATUS.length()))
.orElse(DEFAULT_STATUS);
return Map.of(HELPER_NAME, helper);
}
}

Add the extension to your WireMock configuration:

// add this line after choosing the notifier to use our custom extension within WireMock
.extensions(new StatusHelperExtension()));

Send a request with the custom header:

GET http://localhost:8080/event-status
X-Mock-Behaviour: event-status:IN_PROGRESS

If the header is omitted, the default status “COMPLETED” is returned.

Use Case 3 : Calling Another Service Using Web Hooks

In some scenarios, you may want your mock server to trigger a call to another service (web hook) as part of the response. This is useful for simulating callbacks or event notifications.

Scenario Description: When a specific endpoint is called, WireMock should send a POST request to an external service to simulate a web hook. We use WireMock’s programmatic configuration so the webhooks URL can be set via a JVM property.

Programmatic Webhook Configuration: The following class registers a webhook stub that reads the target URL from a JVM property:

package com.example;

import com.github.tomakehurst.wiremock.WireMockServer;

import static com.github.tomakehurst.wiremock.client.WireMock.*;
import static com.github.tomakehurst.wiremock.http.RequestMethod.POST;
import static org.wiremock.webhooks.Webhooks.webhook;

public class WireMockServerInitializer {

private static final String WEBHOOK_URL_PROPERTY_NAME = “webhook.url”;
private static final String DEFAULT_WEBHOOK_URL = “http://localhost:8080/webhookMethod”;
private static final String WEBHOOK_PATH = “/webhook”;
private static final String WEBHOOK_EXTENSION = “webhook”;
private static final String CONTENT_TYPE_HTTP_HEADER = “Content-Type”;
private static final String CONTENT_TYPE_HTTP_HEADER_VALUE = “application/json”;
private static final String WEBHOOK_PAYLOAD_TEMPLATE = “””
{
“id”: “{{jsonPath originalRequest.body ‘$.id’}}”,
“status”: “{{jsonPath originalRequest.body ‘$.status’}}”
}
“””;

private WireMockServerInitializer() {
}

static void registerWebhook(WireMockServer server) {
server.stubFor(post(urlPathEqualTo(WEBHOOK_PATH))
.willReturn(ok())
.withServeEventListener(WEBHOOK_EXTENSION, webhook()
.withMethod(POST)
.withUrl(System.getProperty(WEBHOOK_URL_PROPERTY_NAME, DEFAULT_WEBHOOK_URL))
.withHeader(CONTENT_TYPE_HTTP_HEADER, CONTENT_TYPE_HTTP_HEADER_VALUE)
.withBody(WEBHOOK_PAYLOAD_TEMPLATE)
));
}
}

Call this method before starting the server:

WireMockServerInitializer.registerWebhook(wm);

Simulated Webhook Endpoint: Since there is no real service, define a static mapping for the webhook receiver:

//file named webhook-mapping.json in mappings folder.
{
“request”: {
“method”: “POST”,
“url”: “/webhookMethod”,
“bodyPatterns”: [
{ “matchesJsonPath”: “$.id” },
{ “matchesJsonPath”: “$.status” }
]
},
“response”: {
“status”: 200,
“bodyFileName”: “responses/webhook-response.json”,
“headers”: {
“Content-Type”: “application/json”
}
}
}

//file named webhook-response.json in responses folder
{
“result”: “Webhook received”,
“received”: true
}

Testing: Start your app with:

java -jar our-application.jar -Dwebhook.url=http://localhost:8080/webhookMethod

Send a POST request:

POST http://localhost:8080/webhook

{
“id”: “my-id”,
“status”: “DONE”
}

You should receive a 200 response, and WireMock will trigger the webhook as configured.

This post demonstrates how to efficiently mock third-party RESTful APIs in Java using WireMock. It covers basic WireMock setup with Maven, static and dynamic response mapping (including header-based templating), and advanced scenarios like simulating webhooks with programmatic configuration. The examples show how to structure your project, configure WireMock for different environments, and extend its functionality for dynamic behaviors. With WireMock, you can quickly create flexible, maintainable mocks for testing and development, making it easier to integrate and test external APIs in your Java projects.