BXUP Track progress & test yourself — free
QA & Testing · Playbook · Core · ~4 min read
QA & TESTING · PLAYBOOK · CORE

Generate Contract-Accurate Mocks from Specs and Recorded Traffic

Half of "flaky" integration tests are really environment-dependency tests: they fail when a downstream service is slow, redeploying, or returning yesterday's schema. Contract-accurate mocks generated from the OpenAPI spec or from recorded traffic kill that class of flake at the source — if you keep the mocks honest.

Tier: Core · Workflow area: Test data & environments

This playbook takes you from an API spec (or a captured request/response log) to a running WireMock or MSW mock layer, with AI doing the tedious translation and a drift check that stops the mocks from quietly lying about the real service.

When to use

USE THIS WHEN

The dependency is the problem

  • Integration tests fail on downstream timeouts, rate limits, or staging redeploys — not on your code.
  • You need error-path coverage (429s, 503s, malformed bodies) the real service will not produce on demand.
  • A partner API has no sandbox, or the sandbox costs money per call.
SKIP IT WHEN

The mock would hide the risk

  • The test exists specifically to verify the real integration — contract tests against the live provider stay live.
  • The dependency's behavior is undocumented and unstable; mock it and you are testing fan fiction.
  • A one-endpoint stub is faster to hand-write than to review.

Prerequisites

  • The dependency's OpenAPI/Swagger spec, or a HAR/log capture of real traffic (scrubbed of tokens and PII before it goes near an assistant).
  • WireMock (JVM/standalone) or MSW (JS/TS front-end and Node), plus Prism if you want spec-driven mocking with zero authored stubs.
  • An AI assistant — Claude or ChatGPT — for spec-to-stub translation and edge-case enumeration.

The recipe

  1. Start with Prism to see what "free" gets you. Prism serves a mock straight from the spec, with generated examples:

    npx @stoplight/prism-cli mock payments-v2.yaml --port 4010
    curl -s localhost:4010/v2/charges/ch_123 | head -5
    
    { "id": "string", "amount": 0, "currency": "string", "status": "succeeded" }
    

    Spec-generated values are schema-valid but semantically useless ("currency": "string"). Prism is your smoke layer; authored stubs are where the value is.

  2. Have the assistant author realistic stubs from the spec. Paste the relevant paths and schemas, not the whole 9,000-line file:

    Here are the /v2/charges paths and Charge/Error schemas from our payments
    OpenAPI spec. Generate WireMock stub mappings (JSON) for:
    - POST /v2/charges happy path: realistic field values, ISO currency, unix timestamps.
    - 402 card_declined and 429 rate_limited using the Error schema exactly.
    - A 200 whose body is valid JSON but MISSING the optional "receipt_url" field.
    Use response templating for the id field. Do not invent fields that are not
    in the schema. If the schema is ambiguous, ask before guessing.
    

    The "do not invent fields" line matters: assistants pad responses with plausible-looking extras, and your client code may start depending on fields the real API never sends.

  3. For recorded traffic, capture then sanitize. WireMock's record mode proxies real calls and writes mappings:

    java -jar wiremock-standalone.jar --port 8080 \
      --proxy-all="https://api.partner.example" --record-mappings
    

    Then hand the recorded mappings to the assistant with one job: "Replace every real account id, email, token, and card fragment with obviously fake but format-valid values. Change nothing else — not status codes, not headers, not field order." Diff its output against the original before committing; the diff should touch only the values you asked about.

  4. Ask for the edge cases the spec implies but the traffic never showed. Recorded traffic is a survey of the happy path. Prompt: "Given this schema, list response shapes a robust client must tolerate that do not appear in these recordings — nulls in optional fields, empty arrays, maximum-length strings, unknown enum values." Turn the plausible ones into stubs; discard the ones the contract genuinely forbids.

  5. Wire the mocks into tests explicitly, not ambiently. MSW example for a front-end suite:

    server.use(
      http.post('*/v2/charges', () =>
        HttpResponse.json(cardDeclined402, { status: 402 })
      )
    );
    

    Each test states the world it runs in. A global "everything is mocked" setup file is how teams forget which behavior is real.

  6. Install the drift check. Mocks rot the day the provider ships v2.1. Add a scheduled CI job that replays each stub's request against the real sandbox (or validates stubs against the latest spec with Prism's --errors mode) and fails on shape mismatch. When it fails, regenerate the affected stubs — same prompts, new spec — rather than patching by hand.

Key Takeaway:

A mock is a cached claim about another team's service. The generation step is cheap and repeatable; the drift check is what makes the claim trustworthy six months later.

Variations

  • Claude Code in the repo: point it at the spec file and your existing stub directory; it will match your naming conventions and templating style without being told.
  • Plain chat assistant: paste schemas in chunks; expect more invented fields, so the schema-validation step carries more weight.
  • Contract-testing shops (Pact): generate the mock and the consumer contract from the same spec excerpt so they cannot disagree; the Pact broker then owns drift detection.

Quality check

  • Every stub body validates against the current spec schema (Prism or openapi-schema-validator in CI).
  • Grep the mappings for anything that looks like a real token, email domain, or card fragment — recorded stubs leak.
  • Error-path stubs use the provider's real error schema, not a generic {"error": "..."} the assistant improvised.
  • The drift job has actually failed at least once in staging — if it has never fired, prove it can by breaking a stub deliberately.

Pitfalls

  • Invented fields. The top failure mode: assistants add created_by, metadata, or camelCase twins of snake_case fields. Schema validation catches this; eyeballs do not.
  • Happy-path recordings promoted to "the contract." Traffic captures show what the service did that Tuesday, not what it may do. Step 4 exists for this reason.
  • Unsanitized captures. A HAR file pasted raw into a chat assistant is a data breach with extra steps. Scrub first, always, even for "internal" services.
  • Mock sprawl. Fifty near-identical stubs nobody owns. Keep stubs beside the tests that use them, and delete with the test.
Pro Tip

Keep the generation prompt in the repo next to the stubs (stubs/PROMPT.md). When the spec changes, anyone can regenerate in two minutes instead of reverse-engineering what the last person asked for — the prompt is the source; the stubs are build artifacts.

This is the free reading view. Open BXUP to track your progress, run the hands-on labs, and prove it with original, exam-pattern assessments.
© Anvi Innovate · BXUP — Be Exponentially Upskilled · BXUP is an independent learning platform, not affiliated with or endorsed by AWS, Microsoft, Google, NVIDIA, IBM, Salesforce, Databricks, Oracle or Anthropic. All trademarks belong to their respective owners. · bxup.in