skip to content

In WireMock, how do you give each stubbed dispatch reply a fresh id and timestamp?

level: juniorimportance: should knowfreq 50%

answer

  1. not every value comes from the request
  2. the reply invents what a service assigns
  3. one helper for ids, one for clocks
  4. WireMock randomValue with a type
  5. WireMock now with offset and format

basics

~20 s

WireMock's randomValue helper generates a value such as a UUID, and its now helper renders the current time, with optional offset and format. Both need the response-template transformer attached, or WireMock serves the raw helper text itself as the body.

solid answer

~50 s

Not everything a dynamic reply needs comes from the request. WireMock's templating ships helpers that invent values: `{{randomValue type='UUID'}}` produces a fresh identifier on every call, and `{{now}}` renders the current instant, with `format='yyyy-MM-dd HH:mm:ss'` choosing the layout and `offset='4 hours'` shifting it forwards or backwards. Written into the body of a `POST /dispatch/v1/assignments` stub, they give every assignment its own `assignmentId` and a `dispatchedAt` that moves with the clock, which is exactly what a client that stores or compares those fields expects to see. Both helpers depend on the same switch as everything else in WireMock templating: without `response-template` in the response's `transformers`, the helper text is served as literal body characters. Generated values are also the ones that make a stubbed reply non-deterministic, so assert on their shape rather than on their content.

code

java · 12 lines
java
import static com.github.tomakehurst.wiremock.client.WireMock.*;

stubFor(post(urlPathEqualTo("/dispatch/v1/assignments"))
    .willReturn(aResponse()
        .withStatus(201)
        .withHeader("Content-Type", "application/json")
        .withBody("{"
            + "\"assignmentId\": \"{{randomValue type='UUID'}}\","
            + "\"dispatchedAt\": \"{{now format='yyyy-MM-dd HH:mm:ss'}}\","
            + "\"expiresAt\": \"{{now offset='4 hours' format='yyyy-MM-dd HH:mm:ss'}}\""
            + "}")
        .withTransformers("response-template")));

go deeper

for a junior

Be ready to name WireMock's randomValue and now helpers and to say that both need the response-template transformer attached. Knowing that they render per request is the core of the answer.

for a middle

Explain the parameters that make them useful — a chosen format and an offset on WireMock's now, a type on its randomValue — and why a hard-coded identifier shared across a suite causes trouble.

for a senior

Talk about the cost: generated values are where a stubbed reply stops being deterministic, so assertions move to shape and snapshot comparison needs the moving fields normalised first.

for a principal

Own the convention for how closely stubbed identifiers must mirror the real service's format, because a stub that teaches clients the wrong shape is a defect that surfaces only in production.

## Two kinds of value a template can produce Response templating in WireMock covers two different needs, and it is worth separating them because they fail differently: - **Derived values** come out of the request being answered — the path, a query parameter, a field lifted from the payload. They make the reply *agree* with the call. - **Invented values** come from nowhere in particular — an identifier, a timestamp, a random string. They make the reply *plausible*, which is what a client expects from a real service that assigns things. A snowplough dispatch API needs both. `POST /dispatch/v1/assignments` should echo back the `routeId` the caller submitted, and it should return an `assignmentId` the caller has never seen and a `dispatchedAt` that reflects when the call happened. A stub that hard-codes the last two returns the same identifier to every test in the suite, which is fine until something downstream treats it as a key. ## Generating an identifier WireMock's `randomValue` helper produces a fresh value per render: - `{{randomValue type='UUID'}}` — WireMock renders a UUID, the usual choice for a synthetic identifier. - `{{randomValue type='ALPHANUMERIC' length=12}}` — WireMock renders a string of a chosen length, for reference codes that are not UUIDs. Because it renders per request, two calls to the same stub get two different values. That is the behaviour a client under test needs when it stores what the service returned and looks it up again. ## Stamping a time WireMock's `now` helper renders the current instant, and it takes parameters: - `{{now}}` — WireMock renders the current time in the helper's default layout. - `{{now format='yyyy-MM-dd HH:mm:ss'}}` — WireMock renders the same instant in a layout you choose, which matters when the client parses it strictly. - `{{now offset='4 hours'}}` — WireMock renders a time shifted forwards, for an expiry or a planned completion. - `{{now offset='-30 minutes'}}` — WireMock renders a time shifted backwards, for a field that should predate the call. The offset is what turns `now` from a convenience into something useful. A dispatch confirmation carrying `dispatchedAt` and an `expiresAt` four hours later is a far better stand-in than one whose two timestamps are identical strings. ## It is still opt-in Both helpers depend on the same switch as every other part of WireMock's templating. Without WireMock's `response-template` in that response's `transformers` — or the instance running with `--global-response-templating` — the body is served as written, and the client receives the helper text itself. This produces a distinctive symptom worth recognising: | What the client receives | What it means | |---|---| | a different UUID on each call | the WireMock template is rendering correctly | | the same UUID on every call | the value was hard-coded, not generated | | the literal helper text | the WireMock transformer is not attached to that response | ## What generated values cost a test Invented values are the point at which a stubbed reply stops being deterministic, and that has consequences: - An assertion on the exact identifier can no longer be written, because it changes per run. Assert on shape — non-empty, well-formed, different from the previous call — instead. - A timestamp that moves makes snapshot comparison of a whole body impossible without normalising the field first. - Two stubs that each generate an identifier cannot be made to agree. If a test needs the same id in two replies, that value has to be fixed, not generated, or carried through the request so both replies derive it. - A generated value proves nothing about the real upstream's format. If the real service issues a prefixed reference rather than a UUID, a stub returning a UUID is teaching the client the wrong shape. ## Choosing between generated and echoed 1. If the client will store the value and use it again, generate it — a constant makes every test in the run share one key. 2. If the client will compare the value with something it sent, echo it out of the request instead; a generated value can never agree with the caller. 3. If a test asserts on the value at all, assert on its shape, and normalise moving timestamps before comparing whole bodies. 4. If the real service's format is known and distinctive, match that format rather than reaching for a UUID because it is the easiest helper to type.

  • How do you assert on a WireMock reply whose assignmentId changes every call?
    Assert on shape rather than value — that the field is present, non-empty and parses as the format the real service uses — and capture the value the client received if a later step needs it. Comparing whole bodies against a snapshot requires normalising both the generated identifier and any timestamp first.
  • When should a WireMock stub return a fixed identifier instead of a generated one?
    When two replies have to agree, or when the test asserts the exact value. A generated identifier is different on every render, so two stubs cannot be made to return the same one. Fix the value, or derive it from something in the request so both replies compute it identically.

A literal stub body is a printed form where every copy carries the same answers. A templated one is a mail merge: the layout is fixed, but the reference number and the date are filled in as each copy is run off.

saying these in an interview costs you the question

  • Hard-codes one identifier and lets the whole suite share it
  • Expects WireMock helpers to render without the transformer attached
  • Asserts on the exact value of a generated WireMock identifier
  • Gives every timestamp in a reply the same rendered instant
  • Returns a UUID when the real service issues a prefixed reference