WireMock Standalone Configuration

This page covers installing, configuring, and integrating the WireMock standalone server — from first startup through CI-ready deployment — but not embedded library usage or framework-specific test runners.


How the standalone model fits the mock stack

The standalone distribution runs as an ordinary HTTP process, separate from application code. This means any language, any test runner, and any CI environment can point requests at it without adding a Java dependency to the application build. The trade-off is explicit lifecycle ownership: you start the process, verify it is ready, and tear it down — unlike embedded libraries that bind to a JUnit or pytest session and clean up automatically.

The diagram below shows where the standalone server sits relative to a typical local development stack:

WireMock standalone in the local dev stack Diagram showing browser or test runner on the left sending requests through the application layer to WireMock standalone, which reads stub files from disk and returns responses. Browser / Test runner HTTP Application / Dev server localhost:3000 proxied API calls WireMock standalone :8080 /__admin API stub engine reads mappings/ __files/ Test runner POSTs to /__admin to reset state

This isolation enables the application under test to treat WireMock exactly like a real upstream service — the same host, port, and protocol — which means no test-only shims in application code.


Prerequisites

  • Java Runtime Environment 11 or later (java -version to check)
  • curl or httpie for health checks and manual verification
  • Docker Engine 24+ (only for Phase 2 Docker deployment)
  • Port 8080 (and 8443 for HTTPS) free on localhost
  • Basic familiarity with JSON request/response structure

Phase 1 — Core setup: first stub in 5 minutes

Download and start the server

# Download the latest standalone JAR (check wiremock.org for the current version number)
curl -Lo wiremock-standalone.jar \
  https://repo1.maven.org/maven2/org/wiremock/wiremock-standalone/3.6.0/wiremock-standalone-3.6.0.jar

# Create the directory structure WireMock expects
mkdir -p mocks/mappings mocks/__files

# Start the server pointing at that root directory
java -jar wiremock-standalone.jar \
  --port 8080 \
  --root-dir ./mocks \
  --global-response-templating \
  --disable-request-journal \
  --verbose

--global-response-templating activates Handlebars templating on every response body so you can reference request data without declaring "transformers" in each stub. --disable-request-journal prevents heap growth in long-running CI jobs by discarding the in-memory request log.

Write your first stub mapping

Create mocks/mappings/users-get.json:

{
  "request": {
    "method": "GET",
    "urlPathPattern": "/api/v1/users/[0-9]+"
  },
  "response": {
    "status": 200,
    "headers": {
      "Content-Type": "application/json"
    },
    "jsonBody": {
      "id": "{{request.pathSegments.[3]}}",
      "name": "Mock User",
      "email": "mock+{{request.pathSegments.[3]}}@example.com",
      "status": "active",
      "createdAt": "{{now format='yyyy-MM-dd'}}"
    }
  }
}

WireMock hot-reloads file-based stubs; no restart is needed. Send a request to confirm:

curl -s http://localhost:8080/api/v1/users/42 | jq .

Expected output:

{
  "id": "42",
  "name": "Mock User",
  "email": "[email protected]",
  "status": "active",
  "createdAt": "2026-06-21"
}

Fault and latency stubs

Fault simulation is a first-class feature: fault values like CONNECTION_RESET_BY_PEER terminate the TCP connection, while fixedDelayMilliseconds injects artificial latency. Both are critical for testing response shaping techniques such as timeout handling and retry budgets.

{
  "request": {
    "method": "GET",
    "urlPath": "/api/v1/payments/slow"
  },
  "response": {
    "status": 200,
    "fixedDelayMilliseconds": 2500,
    "jsonBody": { "status": "settled" }
  }
}
{
  "request": {
    "method": "POST",
    "urlPath": "/api/v1/webhooks/broken"
  },
  "response": {
    "fault": "CONNECTION_RESET_BY_PEER"
  }
}

Phase 2 — Configuration and wiring

Priority and matcher precedence

When multiple stubs match a request, WireMock selects the one with the highest priority value (lower number = higher priority). Declare priority explicitly for any stub that overlaps a broader pattern:

{
  "priority": 1,
  "request": {
    "method": "GET",
    "urlPath": "/api/v1/users/me"
  },
  "response": {
    "status": 200,
    "jsonBody": { "id": "current", "name": "Authenticated User" }
  }
}
{
  "priority": 5,
  "request": {
    "method": "GET",
    "urlPathPattern": "/api/v1/users/[a-z0-9]+"
  },
  "response": {
    "status": 200,
    "jsonBody": { "id": "{{request.pathSegments.[3]}}", "name": "Generic User" }
  }
}

Without explicit priorities, WireMock falls back to insertion order, which is non-deterministic when stubs are loaded from multiple files in parallel.

Header and body matchers

Request matching supports JSON path expressions, regular expressions, and equality checks on headers, query parameters, cookies, and the request body. This enables advanced MSW handler patterns to be mirrored on the server side for full-stack parity:

{
  "request": {
    "method": "POST",
    "urlPath": "/api/v1/orders",
    "headers": {
      "Authorization": { "matches": "Bearer [A-Za-z0-9._-]+" },
      "Content-Type": { "equalTo": "application/json" }
    },
    "bodyPatterns": [
      { "matchesJsonPath": "$.items[?(@.quantity > 0)]" }
    ]
  },
  "response": {
    "status": 201,
    "jsonBody": {
      "orderId": "{{randomValue length=12 type='ALPHANUMERIC'}}",
      "status": "pending"
    }
  }
}

Scenario state machine

Stateful flows (login → session → logout, or order → fulfilment → shipped) use WireMock’s built-in scenario engine. Each stub declares scenarioName, requiredScenarioState, and newScenarioState. This pattern integrates directly with mock lifecycle management principles — state is held in the server process, not the test runner:

{
  "scenarioName": "order-flow",
  "requiredScenarioState": "Started",
  "newScenarioState": "order-placed",
  "request": {
    "method": "POST",
    "urlPath": "/api/v1/orders"
  },
  "response": {
    "status": 201,
    "jsonBody": { "orderId": "ORD-001", "status": "pending" }
  }
}
{
  "scenarioName": "order-flow",
  "requiredScenarioState": "order-placed",
  "request": {
    "method": "GET",
    "urlPath": "/api/v1/orders/ORD-001"
  },
  "response": {
    "status": 200,
    "jsonBody": { "orderId": "ORD-001", "status": "processing" }
  }
}

Reset all scenario states between test runs:

POST http://localhost:8080/__admin/scenarios/reset

Docker service definition

Running WireMock as a Docker service eliminates the JRE prerequisite for team members and CI runners. The official image mirrors the CLI flags exactly, and because the proxy vs inline mocking strategies comparison applies here too — this is a proxy-style external server rather than an inline library — the Docker approach amplifies the language-agnostic benefit:

# docker-compose.yml
version: "3.9"
services:
  wiremock:
    image: wiremock/wiremock:3.6.0
    ports:
      - "8080:8080"
    volumes:
      - ./mocks:/home/wiremock
    command: >
      --global-response-templating
      --disable-request-journal
      --verbose
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost:8080/__admin/health"]
      interval: 5s
      timeout: 3s
      retries: 6
      start_period: 10s

Start and wait for readiness:

docker compose up -d wiremock
docker compose wait wiremock   # exits 0 when healthcheck passes

Phase 3 — CI pipeline integration

GitHub Actions workflow

# .github/workflows/integration-tests.yml
name: Integration tests

on: [push, pull_request]

jobs:
  test:
    runs-on: ubuntu-latest
    services:
      wiremock:
        image: wiremock/wiremock:3.6.0
        ports:
          - 8080:8080
        options: >-
          --health-cmd "curl -f http://localhost:8080/__admin/health"
          --health-interval 5s
          --health-timeout 3s
          --health-retries 6

    steps:
      - uses: actions/checkout@v4

      - name: Copy stub mappings into service container
        run: |
          docker cp ./mocks/mappings/. $(docker ps -qf "ancestor=wiremock/wiremock:3.6.0"):/home/wiremock/mappings/
          docker cp ./mocks/__files/. $(docker ps -qf "ancestor=wiremock/wiremock:3.6.0"):/home/wiremock/__files/

      - name: Run integration tests
        env:
          API_BASE_URL: http://localhost:8080
        run: npm test

For parallel CI jobs sharing a host, bind each WireMock instance to a different port and pass that port as an environment variable (MOCK_PORT) to the test process. Do not use --port 0 (random port) in Docker service definitions — the mapped host port must be declared statically in the ports: array.

Per-suite state reset

Between independent test suites running sequentially against the same WireMock process, reset both mappings and the request journal:

# Restore file-based stubs and clear any programmatically added stubs
curl -X POST http://localhost:8080/__admin/mappings/reset

# Clear the request journal (only relevant if --disable-request-journal is NOT set)
curl -X POST http://localhost:8080/__admin/requests/reset

# Reset all scenario state machines
curl -X POST http://localhost:8080/__admin/scenarios/reset

This three-step reset mirrors managing mock server lifecycles in Docker and ensures each suite starts with a known server state rather than inheriting residual scenario state from a prior run.


Verification steps

  • curl -s http://localhost:8080/__admin/health returns {"status":"running"}
  • curl -s http://localhost:8080/__admin/mappings | jq '.mappings | length' returns the expected stub count
  • curl -s http://localhost:8080/api/v1/users/42 | jq .id prints "42" (templating active)
  • curl -s http://localhost:8080/__admin/requests returns an empty or populated log (confirms journal state)
  • A POST to /__admin/scenarios/reset followed by a scenario-first request returns the initial state response

Troubleshooting

404 with near-match report in the response body

WireMock returns a JSON mismatch report explaining which matchers passed and which failed. Enable --verbose at startup to see this in the server log. The most common causes are:

  • URL pattern mismatch. urlPath requires an exact path without query string; urlPathPattern accepts a regex; url matches the full path including query string. Using the wrong field type silently fails all requests with query parameters.
  • Missing Content-Type header matcher. If the stub declares a bodyPatterns entry, WireMock also validates Content-Type: application/json by default. Add the header to your test request or remove the implicit header check via "ignoreArrayOrder": true in the body pattern.

Port already in use at startup

java.net.BindException: Address already in use

Find and free the process on the port:

lsof -ti:8080 | xargs kill -9

In parallelised CI, use a unique port per test worker:

java -jar wiremock-standalone.jar --port $((8080 + WORKER_INDEX))

Template rendering returns literal Handlebars syntax

The Handlebars expression appears verbatim in the response — for example {{request.pathSegments.[3]}} — instead of being evaluated. Cause: --global-response-templating is absent from the startup flags, or the stub explicitly sets "transformers": [] (an empty list overrides the global setting). Fix: add --global-response-templating to the start command, or add "transformers": ["response-template"] to the stub’s "response" object.

Scenario stuck in wrong state

After an error mid-scenario, the server state machine may be stranded in an intermediate state, causing all subsequent requests to return 404. Reset with:

curl -X POST http://localhost:8080/__admin/scenarios/reset

Automate this in test suite teardown hooks to prevent bleed between runs.

OutOfMemoryError in long-running CI jobs

The request journal accumulates every request in heap memory. Either pass --disable-request-journal at startup (preferred for CI) or periodically flush it:

curl -X DELETE http://localhost:8080/__admin/requests

If you need the journal for debugging, increase heap with -Xmx512m before the -jar flag.


When to advance

The WireMock standalone setup is ready when:

  • All defined stubs return the expected responses and Handlebars templates evaluate correctly.
  • The CI pipeline waits for the health check before running tests, and tests pass consistently across at least three consecutive runs.
  • State reset calls between suites produce a clean server state (confirmed by checking /__admin/mappings count and /__admin/scenarios).
  • Stub files are committed to version control with consistent JSON formatting enforced by a pre-commit hook.

At that point, move on to containerising the environment end-to-end with running WireMock in Docker Compose, or explore setting up WireMock with Spring Boot if the Java application tier needs in-process mocks alongside the standalone server.


FAQ

Does the standalone JAR support recording real API traffic automatically?

Yes. Start with --record-mappings --proxy-all https://api.example.com and WireMock writes a stub file for every proxied request. This accelerates the first pass of stub creation but introduces non-determinism — recorded stubs reference data from a live service at a point in time. For production CI, replace recorded stubs with hand-authored, version-controlled ones as soon as initial coverage is established.

How do I serve different responses based on the request body content?

Use bodyPatterns with a matchesJsonPath or equalToJson matcher in the request definition. Each pattern is evaluated against the parsed request body, and the first stub whose all patterns match wins. Combine this with scenario state to serve different responses on repeated calls to the same endpoint.

Can I run multiple WireMock instances on the same machine?

Yes — each instance needs a distinct --port and --root-dir. Assign ports programmatically in test orchestration scripts using environment variables, and verify each instance independently via its /__admin/health endpoint before routing traffic to it.

Does WireMock standalone handle WebSocket connections?

Not in the standalone JAR for general WebSocket proxying. For WebSocket-heavy frontends, evaluate Mock Service Worker MSW setup which intercepts at the browser’s Service Worker layer, or use a dedicated WebSocket mock server alongside WireMock for HTTP.


← Back to Tool-Specific Implementation & Setup