skip to content

Response Templating

A reply computed from the request it answers, not frozen at definition time - Handlebars in WireMock, decorate and copy in Mountebank. Forget to switch the transformer on and you return the source.

on this pageshow

explore

questions

5

In WireMock, why does a stubbed body containing `{{request.path}}` come back unrendered?

level: juniorimportance: must knowfreq 66%

answer

  1. rendering is opt-in, not automatic
  2. the body was served, not interpreted
  3. something must name the transformer
  4. WireMock resolves response-template exactly
  5. WireMock withTransformers, or the global flag

basics

~20 s

WireMock renders a stub body only when the response-template transformer is attached to that response. Without it, WireMock treats the body as literal bytes and returns the Handlebars source unchanged. Attach it with withTransformers, or launch WireMock with --global-response-templating.

solid answer

~40 s

Response templating in WireMock is opt-in per response, not a global default. A WireMock response definition renders Handlebars only when the `response-template` transformer is attached to it, so a body written as a template but served without that attachment goes out byte for byte and the caller receives the literal characters `{{request.path}}`. Attach it in WireMock's Java DSL with `aResponse().withBody(...).withTransformers("response-template")`, or in a WireMock JSON stub mapping with `"transformers": ["response-template"]` inside the `response` object rather than beside it. WireMock never warns you about this: it does not scan bodies for braces, so an unrendered template is a perfectly valid 201 carrying a payload the client cannot use. If a whole standalone instance is dynamic, start WireMock with `--global-response-templating`; `--local-response-templating` is WireMock's explicit name for the opt-in default you already have.

go deeper

for a junior

Be ready to say that WireMock templating is opt-in and to name the string response-template. Knowing that a missing transformer produces a literal body rather than an error is the whole first-screen answer.

for a middle

Explain the mechanics: where the transformer name goes in the Java DSL and in a JSON mapping, that rendering happens after matching, and that WireMock gives no warning when a template is served unrendered.

for a senior

Show how you would diagnose it on a running instance — read the mapping back, check the exact spelling, then check how the server was launched — and say why silence rather than an error is the dangerous part.

for a principal

Own the instance-wide choice: whether a shared WireMock renders every response by default or opts in per stub, and what that decision costs a team whose fixture bodies legitimately contain braces.

## What response templating is A WireMock stub mapping has two halves: a request pattern that decides which calls it answers, and a response definition that says what comes back. By default that response definition is inert — the bytes you handed to WireMock's `aResponse().withBody(...)` are the bytes written to the socket. That is the right default. Most stubs want a fixed payload, and a server that tried to interpret every body would mangle the ones that legitimately contain braces. Response templating is the opt-in that changes it. When a WireMock response is templated, the server passes the body and the header values through **Handlebars** before sending them, so a body written as `{"acceptedPath": "{{request.path}}"}` leaves the server as `{"acceptedPath": "/dispatch/v1/assignments"}`. The component that performs this in WireMock is `ResponseTemplateTransformer`, and the name a mapping refers to it by is the exact string **`response-template`**. ## Why a template comes back as text There is one cause worth checking before any other: the transformer is not attached to that response. WireMock does not sniff bodies for `{{`, it does not log a warning when a body looks like an unrendered template, and it does not fail the request. WireMock answers with the status you asked for and a payload containing the literal characters `{{request.path}}`. Downstream that surfaces as a deserialisation failure or, worse, as those braces being stored as a snowplough route identifier. The attachment goes missing in four recognisable ways: - The WireMock Java DSL chain stops one call early: `aResponse().withBody(...)` with no `.withTransformers("response-template")` after it. - A WireMock JSON stub mapping carries `"transformers": ["response-template"]` at the top level of the mapping instead of inside its `response` object, which is where the server looks. - The name is spelled `responseTemplate`, `response_template` or `ResponseTemplateTransformer`, none of which WireMock resolves, because it matches the transformer by that one exact string and renders nothing otherwise. - The mapping is fine, but it was written for a WireMock instance launched with `--global-response-templating` and is being served by one running the opt-in default. ## Attaching it, in both dialects In WireMock's Java DSL the switch is one call on the response builder: ```java stubFor(post(urlPathEqualTo("/dispatch/v1/assignments")) .willReturn(aResponse() .withStatus(201) .withBody("{{request.path}} accepted") .withTransformers("response-template"))); ``` In a WireMock JSON mapping it is an array inside the response object: ```json { "request": { "method": "POST", "urlPath": "/dispatch/v1/assignments" }, "response": { "status": 201, "body": "{{request.path}} accepted", "transformers": ["response-template"] } } ``` Both forms say the same thing to the same component, and neither of them changes matching. Templating decides what the reply contains; it never decides which stub answers. ## Per stub, or for the whole server Two WireMock standalone flags set the default for an instance: 1. `--global-response-templating` makes every response that WireMock instance serves render. It suits an instance whose entire mapping set is dynamic, and it removes the per-mapping noise of repeating the transformer name in every file. 2. `--local-response-templating` states WireMock's opt-in default out loud: a response renders only if it asked to. It is the safer setting for a mixed set, because a fixture body that legitimately contains `{{` — a page fragment, a configuration document, some other tool's template — is then served untouched. Deciding this once per instance is cheaper than rediscovering it per stub, and the choice belongs in whatever starts the server, not in the mappings. ## The same idea, three different shapes | Server | How a reply becomes dynamic | What people get wrong | |---|---|---| | WireMock | attach the `response-template` transformer to the response, or launch with `--global-response-templating` | the transformer is simply not attached, so the Handlebars source ships as data | | MockServer | build the reply as a template with `HttpTemplate.template(TemplateType.VELOCITY, ...)` instead of a literal `response()` | there is nothing to attach — a template and a literal reply are different kinds of response | | Mountebank | add `decorate`, `copy` or `lookup` to that response's `behaviors` array | quoting `repeat` as a behavior, when it is a field on the response and not one of the five behaviors | The first row is the one this question turns on. WireMock is the server of the three where a perfectly well-formed template can be defined and then never run, because the decision to render lives somewhere other than the body itself. ## Diagnosing it in three steps 1. Fetch the mapping back from the running WireMock instance and look for the transformer name inside the `response` object. If it is absent, that is the whole bug. 2. If it is present, compare the spelling with WireMock's `response-template` character by character; a near miss registers no transformer and produces exactly the same symptom. 3. If both are right, check how the instance was launched — a mapping that quietly relies on `--global-response-templating` behaves differently on a WireMock instance that never got the flag.

  • Where exactly does the transformers array go in a WireMock JSON stub mapping?
    Inside the `response` object, alongside `status` and `body` — not at the top level of the mapping and not inside `request`. WireMock reads transformer names off the response definition, because templating is a property of the reply, so a correctly spelled array in the wrong place is ignored in silence and looks identical to having forgotten it.
  • Does WireMock templating apply to anything other than the response body?
    Yes — with the `response-template` transformer attached, WireMock renders response header values as well as the body, so a stub can echo a correlation id from the request into a reply header. Matching is untouched: the request pattern that selects the stub is evaluated before any rendering happens.
  • What is the risk of turning on WireMock's --global-response-templating everywhere?
    Every response on that WireMock instance is then parsed as Handlebars, including bodies that contain braces for their own reasons. A fixture that is itself a template, or a document with `{{` in it, stops coming back verbatim. Global templating is right when the whole set is dynamic and a liability when it is mixed.

saying these in an interview costs you the question

  • Assumes WireMock renders any body that contains double braces
  • Puts a WireMock mapping transformers array beside the response, not inside it
  • Thinks an unrendered template makes WireMock fail the request
  • Spells the transformer responseTemplate and expects WireMock to resolve it
  • Believes templating changes which WireMock stub matches the request
open as a page

In WireMock, how do you build a stubbed reply out of the request that triggered it?

level: middleimportance: must knowfreq 62%

basics

~20 s

Attach WireMock's response-template transformer, then reference the request model from the body. WireMock exposes the call as request, so request.path, request.query and request.body are readable, and the jsonPath helper pulls a single field out of a JSON payload.

open as a page

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

level: juniorimportance: should knowfreq 50%

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.

open as a page

When should a WireMock stub server run --global-response-templating rather than per-stub templating?

level: seniorimportance: should knowfreq 48%

basics

~20 s

Turn on WireMock's --global-response-templating when every mapping on that instance is dynamic and repeating the transformer name is pure noise. Keep per-stub templating for a mixed set, because global rendering parses every body, including ones that legitimately contain braces.

open as a page

In WireMock, why does a templated body render " where a quote should be?

level: seniorimportance: should knowfreq 44%

basics

~20 s

Handlebars escapes double-brace output for HTML, so WireMock turns a quote into the " entity. In WireMock, the triple-brace form emits the helper's output raw instead. Use it whenever a WireMock template injects JSON or XML into a reply.

open as a page