Tutorial: Learn WireMock from Scratch (2026)
I once spent three days debugging a test failure only to discover the third-party API sandbox was down. That is when I decided to take control of my external dependencies in tests. WireMock lets you stub HTTP services deterministically, so your tests are fast, reliable, and independent of external systems.
WireMock is a flexible HTTP mock server for testing. You define stub mappings that match incoming requests and return configured responses. It supports request verification, fault injection, and stateful behavior. This tutorial covers everything from basic stubbing to advanced simulation scenarios.
Setting Up WireMock and Your First Stub
WireMock can run standalone as a Java process or embedded in your tests. For Java projects, add the wiremock dependency and use WireMockServer in your test. The server listens on a configurable port and matches requests against registered stubs.
A stub mapping defines a request pattern and a response. Use stubFor with the WireMock static API. The simplest stub returns a fixed response with a status code and body. WireMock matches on URL, HTTP method, headers, query parameters, and request body.
WireMockServer wireMockServer = new WireMockServer(8080);
wireMockServer.start();
configureFor("localhost", 8080);
stubFor(get(urlEqualTo("/api/users/1"))
.willReturn(aResponse()
.withStatus(200)
.withHeader("Content-Type", "application/json")
.withBody("{\"id\":1,\"name\":\"Alice\"}")));
Request Matching Strategies
WireMock matches requests using URL, method, headers, cookies, query parameters, and body. URL matching supports exact path, URL pattern (regex), and URL path pattern. Headers and query parameters can match with exact values or regular expressions.
For body matching, use matchingJsonPath for JSON APIs, matchingXPath for XML, or equalToJson for strict JSON equality. Priority-based stubs let you define a default response and override it for specific cases. I use this pattern to stub most requests with generic responses and specific ones for edge cases.
stubFor(get(urlPathMatching("/api/users/[0-9]+"))
.withHeader("Authorization", matching("Bearer .*"))
.withQueryParam("fields", equalTo("id,name,email"))
.willReturn(aResponse()
.withStatus(200)
.withBody("{\"id\":1,\"name\":\"Alice\"}")));
Verifying Requests and Interactions
Request verification ensures the system under test made the expected calls. Use verify with the same request matching criteria used in stubs. Check exact call count, at least, at most, or no calls. Verification is essential for confirming that your code calls external APIs correctly.
I verify both the occurrence and the content of requests. For example, verify that a POST request was made with the correct JSON body. Verification failures provide detailed diagnostics showing what was received versus what was expected.
verify(postRequestedFor(urlEqualTo("/api/orders"))
.withRequestBody(matchingJsonPath("$.productId", equalTo("123")))
.withRequestBody(matchingJsonPath("$.quantity", equalTo("2"))));
verify(exactly(1), getRequestedFor(urlPathMatching("/api/users/.*")));
verify(0, postRequestedFor(urlEqualTo("/api/admin")));
Simulating Faults and Delays
WireMock can simulate network faults that are hard to reproduce with real services. Inject random or fixed delays to test timeouts. Return 500 errors, malformed responses, or close the connection abruptly to test error handling.
Use withFixedDelay for consistent timing and withRandomDelay for variable timing. The withFault method can return an empty response, a malformed chunked response, or a connection reset. I test my application's resilience by simulating these failure modes in separate test scenarios.
// Simulate slow response
stubFor(get(urlEqualTo("/api/slow"))
.willReturn(aResponse()
.withFixedDelay(5000)
.withStatus(200)
.withBody("{\"status\":\"delayed\"}")));
// Simulate server error
stubFor(get(urlEqualTo("/api/error"))
.willReturn(aResponse()
.withStatus(500)
.withBody("Internal Server Error")));
Stateful Behavior with Scenarios
Scenarios model stateful API behavior where responses depend on previous requests. Define a scenario with states and transitions. The first request puts the scenario in a new state, and subsequent requests return different responses based on the current state.
This is useful for testing multi-step workflows like order processing — create order returns pending, payment processing returns processing, and payment confirmation returns completed. Scenarios keep your stubs aligned with the actual API contract.
stubFor(post(urlEqualTo("/api/orders"))
.inScenario("Order Processing")
.whenScenarioStateIs(Scenario.STARTED)
.willReturn(aResponse()
.withStatus(201)
.withBody("{\"status\":\"pending\"}"))
.willSetStateTo("Payment Pending"));
stubFor(post(urlEqualTo("/api/orders/pay"))
.inScenario("Order Processing")
.whenScenarioStateIs("Payment Pending")
.willReturn(aResponse()
.withStatus(200)
.withBody("{\"status\":\"completed\"}")));
WireMock in CI and Best Practices
WireMock integrates with JUnit via @WireMockTest, which starts and stops the server automatically. For Spring Boot tests, use @AutoConfigureWireMock. The standalone JAR can run as a Docker container for shared test environments.
Best practices: keep stub definitions close to the tests that use them, use JSON mapping files for complex stubs, reset the server between tests with resetAll(), and use recordings (proxying) to capture real API responses as stubs. Always verify that all expected requests were made.
@WireMockTest(httpPort = 8080)
class OrderServiceTest {
@Test
void shouldCreateOrder() {
// WireMock is running on port 8080
// Stubs defined inline or in mapping files
// Run your test that calls http://localhost:8080
// Verify interactions
}
}
Frequently Asked Questions
What is the difference between WireMock and MockServer?
Both are HTTP mock servers. WireMock focuses on flexible stub matching and request verification. MockServer supports more protocols including TLS and forwarding. WireMock has a cleaner API and is more popular for REST API testing.
Can WireMock record real API responses?
Yes, WireMock can act as a proxy that records real API responses to JSON mapping files. Run WireMock in record mode, send requests through it, and it saves the responses as stubs that can be replayed later.
How do I handle authentication in WireMock stubs?
WireMock can match Authorization headers, validate JWT tokens using custom request matchers, or return specific responses based on the auth header value. Use withHeader matching for declarative auth handling.
Does WireMock support HTTPS?
Yes, WireMock can generate self-signed certificates for HTTPS. Configure withHttps() on the server or use the WireMockRule with HTTPS option. For production-like scenarios, provide custom keystores.
Originally published on Ayodhyyya. Last updated June 1, 2026.