Skip to content

Lesson 04 · Mocking Services with WireMock

Beyond the 1Z0-830 exam

Your service usually depends on other HTTP services. Calling the real ones in tests is slow, flaky, and can't easily simulate failures. WireMock is a programmable HTTP mock server: you stub the responses the dependency would return, then test your code against the stub.

Objectives

After this lesson you will be able to:

  • Explain what a mock HTTP server is and when to use one.
  • Stub responses and match requests by method, URL, headers, and body.
  • Verify that your code made the expected calls.
  • Simulate errors, delays, and edge cases a real service rarely produces on demand.

Why a mock server

Your in-JVM HttpServer in the lab is a hand-rolled version of this idea. WireMock makes it declarative and feature-rich. Use it to test the code that calls a dependency, in isolation:

  • Deterministic — the same response every run; no network flakiness.
  • Fault injection — force 500s, timeouts, malformed bodies on demand.
  • Offline & fast — no real service, no credentials, no rate limits.

Stubbing a response

java
WireMockServer wm = new WireMockServer(options().dynamicPort());
wm.start();

wm.stubFor(get(urlEqualTo("/widgets/1"))
    .willReturn(aResponse()
        .withStatus(200)
        .withHeader("Content-Type", "application/json")
        .withBody("{\"id\":1,\"name\":\"Gizmo\",\"inStock\":true}")));

// Point your client at wm.baseUrl(), call it, assert on the result…

Requests that don't match any stub return 404 by default, so a mismatched URL fails loudly.

Matching requests

Stubs can match on much more than the URL — method, query params, headers, and the body:

java
wm.stubFor(post(urlPathEqualTo("/widgets"))
    .withHeader("Content-Type", equalTo("application/json"))
    .withRequestBody(matchingJsonPath("$.name", equalTo("Gizmo")))
    .willReturn(aResponse().withStatus(201)
        .withHeader("Location", "/widgets/42")));

Verifying interactions

Like Mockito's verify (Module 14), confirm your code actually called the dependency as expected:

java
wm.verify(postRequestedFor(urlEqualTo("/widgets"))
    .withRequestBody(matchingJsonPath("$.name")));

Simulating failure and latency

This is where mocks earn their keep — exercising paths the real service won't give you on demand:

java
wm.stubFor(get("/flaky").willReturn(aResponse()
    .withStatus(503)));                              // does your retry/back-off work?

wm.stubFor(get("/slow").willReturn(aResponse()
    .withFixedDelay(3000)));                          // does your timeout fire?

Gotcha — mocks can drift from reality

A stub encodes your belief about the dependency. If the real service changes its response shape, your green tests are now lying. Combine stubbed tests (fast, broad) with a smaller set of real integration or contract tests (Module 19) that catch drift.

Contract & schema checks

WireMock can validate that your stubs (and recorded traffic) match a published OpenAPI/JSON Schema, nudging you toward contract testing — verifying both sides agree on the API shape. Module 19 takes this further with consumer-driven contracts (Pact).

SDET note

The lab's in-JVM HttpServer is a minimal WireMock: it stubs /widgets/1, a 404 path, and a POST that returns 201. Reading the test, you can see the pattern WireMock formalizes — stub, drive your client, assert. Graduating to WireMock buys you request matching, verification, and fault injection without writing a server by hand.

Key Takeaways

  • A mock HTTP server (WireMock) stands in for a real dependency so you can test the calling code in isolation.
  • Stub responses and match requests by method/URL/headers/body; unmatched requests return 404.
  • Verify the expected calls were made, like Mockito's verify.
  • Mocks shine at fault injection500s, timeouts, malformed bodies on demand.
  • Pair fast stubbed tests with real integration/contract tests so stubs don't drift from reality.

Lesson Quiz

Lesson Quiz · WireMock0 / 5
  1. What problem does WireMock solve?

    • ACompiling Java faster
    • BStanding in for a real HTTP dependency by serving programmed responses
    • CRunning the database
    • DFormatting JSON
  2. A request that matches no configured stub returns…

    • A200 with empty body
    • B404 by default
    • CA random response
    • DThe last stub
  3. Which is a key advantage of stubbing over calling the real service in tests?

    • AStubs are always more accurate
    • BYou can deterministically simulate errors, timeouts, and edge cases on demand
    • CIt removes the need for any integration tests
    • DIt tests the real network
  4. How is WireMock's verify(...) like Mockito?

    • AIt compiles the code
    • BIt confirms your code actually made the expected request(s)
    • CIt mocks Java objects in-process
    • DIt records video
  5. Why pair stubbed tests with real integration/contract tests?

    • ATo slow the suite down
    • BA stub encodes your assumption about the dependency; if the real API changes, stubbed tests still pass but lie
    • CIntegration tests replace unit tests
    • DContracts are required by the JVM

Next: Module 18 · UI / Browser Automation. This module's lab is in labs/src/main/java/com/jse21/m17_api/.