skip to content

Staying Current

How a mapping set is kept aligned with the service it stands in for: regenerated from live traffic, or built by the server itself out of a specification the team already publishes.

on this pageshow

explore

questions

8

In WireMock, what does makeStubsPersistent(false) change about the stubs a re-recording produces?

level: juniorimportance: must knowfreq 58%

answer

  1. in memory only, or also on disk
  2. the default keeps the files
  3. false leaves the working tree clean
  4. a diff needs files to diff
  5. mappings/ for stubs, __files/ for bodies

basics

~20 s

With makeStubsPersistent set to false, WireMock keeps the regenerated stubs in memory only: they serve requests while the instance lives and vanish on restart. Its default, true, writes each one as a JSON file under the mappings directory.

solid answer

~50 s

`makeStubsPersistent(` is the switch on WireMock's record specification that decides whether a regenerated stub is only an object inside the running instance or also a file on disk. Left at its default of `true`, every mapping the refresh produces is written as JSON under the WireMock instance's `mappings/` directory, with any extracted body beside it under `__files/` — which is exactly what you need when the point of the run is to diff the new set against the committed one. Set to `false`, the regenerated stubs are registered in the running instance and nothing is written: WireMock's `GET /__admin/mappings` still lists them and they still answer requests, but a restart loses them and there is nothing to commit or compare. For a refresh of the district heating meter API set, persist. For a throwaway exploratory capture you never intend to keep, `false` leaves the working tree clean.

code

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

configureFor("localhost", 8081);

// keep it: files land under mappings/ and __files/, ready to diff
startRecording(recordSpec()
    .forTarget("https://meters.stadtwaerme.example")
    .makeStubsPersistent(true));

meterClient.readings("DE-HH-4471", "2026-01-01", "2026-01-31");
stopRecording();

// throwaway probe: registered in the running instance, nothing written
startRecording(recordSpec()
    .forTarget("https://meters.stadtwaerme.example")
    .makeStubsPersistent(false));

meterClient.substationFlow("HH-NORD-12");
stopRecording();

go deeper

for a junior

Know the plain meaning of WireMock's switch: true writes the regenerated mappings to disk under the WireMock instance's mappings/ directory, while false keeps them only in memory. Say which one a refresh you intend to commit needs.

for a middle

Explain why the setting matters for a refresh rather than just what it does — a diff against the committed set needs durable files, and the root directory the instance runs with decides where they land.

for a senior

Show that persistence is only step one. Talk about persisting into a clean root, labelling the output with where and when it was captured, and treating the files as unreviewed candidates rather than a new baseline.

for a principal

Decide the policy: who may run a persisted refresh against production, where the output is allowed to be written, and how you keep a directory of stale regenerated captures from accumulating in the repository unread.

## The switch, and the two things it decides In WireMock, `makeStubsPersistent(` sits on the record specification and answers exactly one question: when the recorder turns captured traffic into stub mappings, do those mappings exist only as objects inside the running instance, or also as files on disk? Left at its default of `true`, each regenerated mapping is serialised as JSON under the WireMock instance's `mappings/` directory, and any response body the recorder extracts to its own file is written beside it under `__files/`. Set to `false`, the same mappings are registered in the running instance and **nothing is written at all**. Both settings produce a working stub server. WireMock's `GET /__admin/mappings` lists the regenerated mappings either way, and the district heating meter API stubs answer `GET /v1/meters/DE-HH-4471/readings` either way. The difference is entirely about what survives the process. ## Why a refresh almost always wants true Refreshing means regenerating a mapping set from the live upstream and comparing it to the set already committed in the repository. That comparison needs two sets of files sitting still long enough for a diff tool, a reviewer and a commit to touch them. In-memory stubs cannot be diffed, cannot be reviewed in a pull request, and cannot be partially accepted. So the persistent branch is the one that makes a refresh a refresh: - The regenerated mappings land in a directory you can point `diff` at. - Extracted bodies land under WireMock's `__files/` directory, where the committed set already keeps its bodies, so like compares to like. - A reviewer can accept some regenerated mappings and reject others, file by file. - The run is reproducible: the same replay against the same upstream leaves the same artefacts to look at again tomorrow. ## When false is the right answer - **Exploring an unfamiliar endpoint.** You want to see what the meter API returns for a substation flow query, and you have no intention of keeping it. - **A capture inside a single test method** whose stubs should die with the instance, so no later test inherits them. - **A read-only or containerised working directory** where writing into WireMock's `mappings/` would either fail or pollute an image layer. - **A first pass whose only job is to size the problem** — how many distinct calls does the client actually make? — before you decide what to record properly. ## What persistence does not do - It does not tidy the output. Persisted mappings are raw recordings: literal matchers, whatever headers were captured, whatever body came back. - It does not merge with the committed set. Regenerated files are new files in whichever root the instance is using; they do not update the old ones in place. - It does not make the stubs authoritative. A persisted mapping is a candidate you have not reviewed yet. - It does not stop the recorder from being pointed at the wrong place. Persisting a capture taken from staging simply gives you a durable record of staging. ## What lands on disk | artefact | WireMock directory | notes | |---|---|---| | regenerated stub mapping | `mappings/` | one JSON file per mapping, named by WireMock from the request plus a generated suffix | | extracted response body | `__files/` | written only when WireMock's recorder pulls the body out into its own file | | nothing at all | — | what WireMock's `makeStubsPersistent(false)` writes | The directory those two live under is whichever root the instance was started with, so a refresh that means to leave the committed set alone starts a second WireMock instance on a clean root and persists there. That combination — WireMock's `makeStubsPersistent(true)` plus a root that is not the committed one — is the safe default shape for a refresh run. ## Reading the result Once the files exist, the interesting work begins. Open the regenerated mappings for the paths you care about and read them against their committed counterparts: same status code, same body shape, same headers that the committed matchers depend on? A persisted refresh is worth exactly as much as the attention someone pays to its output, and its value decays fast — a set regenerated three months ago and never reviewed is just a second stale set. One practical habit: persist into a directory whose name records when and against what the capture was taken, such as `refreshed-meters-prod/`. It costs nothing, and it stops a reviewer six weeks later from having to guess whether the files in front of them came from production or from somebody's laptop pointing at a staging deployment of the meter API.

  • If the stubs are in memory only, can a test still assert against them?
    Yes. Non-persistent regenerated stubs are fully registered in the running WireMock instance, so they match requests, return the recorded responses, and appear in WireMock's `GET /__admin/mappings` listing. What you lose is durability — a restart discards them — and reviewability, because there is no file for a diff tool or a pull request to show anyone.
  • Which directory do persisted regenerated mappings actually land in?
    Under the root the WireMock instance is running with, which means `mappings/` for the stub JSON and `__files/` for any extracted body. That is why a refresh starts a second instance on a clean root — persisting into the committed root would scatter freshly named files among the ones you were trying to compare against.

saying these in an interview costs you the question

  • Thinks false discards the stubs so the instance serves nothing
  • Believes persisted mappings merge into the committed files
  • Assumes a persisted recording is reviewed and ready to commit
  • Cannot say which directory holds mappings versus response bodies
  • Persists a capture taken from staging and labels it a production refresh
open as a page

In MockServer, what does upsert(openAPIExpectation(...)) build from an OpenAPI document?

level: middleimportance: must knowfreq 66%

basics

~20 s

MockServer reads the OpenAPI document, then creates one expectation for each operation it selects, matching that operation's method, path and declared parameters. Each expectation replies with the response the document declares. The entry point is upsert(OpenAPIExpectation...) on MockServerClient.

open as a page

In MockServer, how do you make one operation of a spec-derived beehive telemetry mock answer 503?

level: seniorimportance: should knowfreq 53%

basics

~20 s

MockServer's OpenAPIExpectation takes withOperationsAndResponses, a map from operation id to the response that operation should answer with. Mapping getHiveWeight to 503 makes only that operation fail. The map also selects the set: unlisted operations get no expectation at all.

open as a page

In MockServer, what does withSpecUrlOrPayload() accept, and what changes when you point it at a URL?

level: seniorimportance: should knowfreq 51%

basics

~20 s

MockServer's withSpecUrlOrPayload accepts a URL, a file or classpath location, or the OpenAPI document inline. A URL is resolved when upsert runs, so the expectation set becomes whatever that host served then. A pinned copy trades currency for reproducibility.

open as a page

Why does a regenerated WireMock mapping set diff noisily against the committed meter-API set?

level: seniorimportance: should knowfreq 47%

basics

~20 s

Most of the diff is churn, not change. WireMock gives every regenerated mapping a fresh id and a generated file name, and volatile response values differ per call. Normalise both sets, then compare request and response pairs.

open as a page

In WireMock, how do you regenerate a committed mapping set by re-pointing recordSpec().forTarget( at the live meter API?

level: seniorimportance: should knowfreq 64%

basics

~20 s

Point a fresh WireMock recording at the live district heating meter API with forTarget, replay the same traffic, and let the recorder write a new mapping set. Then diff that set against the committed one rather than overwriting it blindly.

open as a page

In MockServer, how would you choose between a document's declared examples and withGenerateFromSchema() across many teams' beehive telemetry mocks?

level: principalimportance: should knowfreq 45%

basics

~20 s

Prefer the document's declared examples: MockServer returns a body a person wrote and a reviewer saw. Use withGenerateFromSchema on MockServer's HttpResponse where only a schema exists. Treat generated values as structurally valid and semantically meaningless, and never assert on them.

open as a page

How would you govern one WireMock proxyAllTo( canary mapping against the live meter API across many suites?

level: principalimportance: should knowfreq 44%

basics

~20 s

Keep one proxy mapping pointed at the live meter API, sitting below every recorded stub so it only fires on an uncovered call. Run it on a scheduled job rather than every suite, and make it removable by metadata.

open as a page