Authors WireMock stub mappings for HTTP service mocking - `stubFor` with verb/path/header matchers + `willReturn` response shaping, lifecycle via `WireMockServer` (start / stop) or JUnit `WireMockExtension`, request verification via `verify()`, and dynamic-port allocation for parallel tests. Use when the project is JVM-based and tests need to mock HTTP dependencies (third-party APIs, internal microservices) at the network layer.
76
95%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Passed
No findings from the security scan
This skill covers the JVM Java API for WireMock stub-mapping authoring
and request verification (wiremock-quickstart). WireMock
also has standalone JAR + Docker modes for non-JVM consumers - the
matching skill for JS / TS is msw-handlers.
<dependency>
<groupId>org.wiremock</groupId>
<artifactId>wiremock</artifactId>
<version>${wiremock.version}</version>
<scope>test</scope>
</dependency>(Per wiremock-quickstart; pin ${wiremock.version} to
the team's chosen 3.x release.)
testImplementation 'org.wiremock:wiremock:3.x' // pin to the chosen release@RulePer wiremock-quickstart:
import com.github.tomakehurst.wiremock.junit.WireMockRule;
import org.junit.Rule;
public class MyServiceTest {
@Rule
public WireMockRule wireMockRule = new WireMockRule(8089);
@Test
public void example() {
stubFor(post("/my/resource")
.withHeader("Content-Type", containing("xml"))
.willReturn(ok()
.withHeader("Content-Type", "text/xml")
.withBody("<response>SUCCESS</response>")));
// ... test the SUT against http://localhost:8089
}
}@WireMockTestFor JUnit 5, use @WireMockTest (or WireMockExtension for
finer control):
import com.github.tomakehurst.wiremock.junit5.WireMockTest;
import org.junit.jupiter.api.Test;
@WireMockTest(httpPort = 8089)
class MyServiceTest {
@Test
void example() {
stubFor(get("/orders/42")
.willReturn(jsonResponse(
"{\"order_id\": 42, \"status\": \"shipped\"}", 200)));
// exercise SUT against http://localhost:8089/orders/42
}
}Pair @WireMockTest with dynamic-port allocation
(wireMockConfig().dynamicPort()) for parallel tests, then read
the assigned port via WireMockRuntimeInfo.
The request-matcher DSL (get / urlPathMatching / withHeader /
withQueryParam / matchingJsonPath / withCookie, first-match-wins),
the response builders (ok() / okJson() / withFixedDelay /
withChunkedDribbleDelay), and stateful scenario stubs are cataloged
in references/matchers-and-scenarios.md.
After exercising the SUT, assert on requests received:
verify(postRequestedFor(urlEqualTo("/orders"))
.withRequestBody(matchingJsonPath("$.sku", equalTo("SKU-1"))));
verify(exactly(1), getRequestedFor(urlPathEqualTo("/health")));verify() throws on mismatch - fails the test with a clear
explanation of expected vs. actual requests.
# .github/workflows/integration.yml (excerpt)
- name: Run integration tests
run: mvn -B verify # WireMock starts in-process per @WireMockTest annotation
- name: Upload WireMock logs
if: failure()
uses: actions/upload-artifact@v4
with:
name: wiremock-logs
path: |
target/wiremock-*.log
target/surefire-reports/
retention-days: 14WireMock writes to JUL by default; route to your project's logger to capture stub-match misses (a common cause of "test passed locally, failed on CI" puzzles).
| Anti-pattern | Why it fails | Fix |
|---|---|---|
| Hard-coded port 8089 across many test classes | Port collisions in parallel test execution. | Use wireMockConfig().dynamicPort(); read the assigned port from runtime info. |
Stubs that match everything (get(anyUrl())) | Hides bugs - your SUT calls a wrong URL and the test still passes. | Match on specific paths; use verify() to assert exact URLs. |
Skipping verify() after exercising the SUT | The test passes if the SUT skips the call entirely (broken control flow). | Always verify() the expected request was made. |
| Standalone WireMock as a separate process in CI | Race conditions on startup; harder to debug. | Prefer in-process WireMock via @WireMockTest; standalone only when you must mock from outside the JVM. |
| Recording from production | Captures real PII; hard to scrub. | Record from staging only; if from prod, post-process to strip PII. |
msw-handlers - JS / TS counterpart
(for browser + Node).mountebank-imposters -
multi-protocol alternative (HTTP + TCP + SMTP).