In WireMock, how does snapshotRecord() differ from a startRecording() session for kayak-rental traffic?
answer
- one looks forward, one looks back
- no session needed for the second
- already-served traffic becomes mappings
- the snapshot form needs no target
- snapshot twice and you convert twice
basics
~20 sIn WireMock, startRecording arms a session ahead of time and proxies to the target from that moment. WireMock's snapshotRecord works backwards instead, turning traffic the server has already served into stub mappings, so it needs no session opened first.
solid answer
~50 sBoth produce the same artefact — WireMock stub mappings — but they act at opposite ends of the traffic. WireMock's `startRecording("https://kayaks.riverbend.example")` is prospective: it proxies to the kayak-rental service and captures from that moment until `stopRecording()` closes the window. WireMock's `snapshotRecord()` is retrospective: it converts what the server has *already* served into mappings and returns a `SnapshotRecordResult`, with `POST /__admin/recordings/snapshot` as the admin equivalent. That matters when proxying was already arranged — a suite that has been running against a proxying WireMock all morning can be snapshotted without re-driving the client at all. It also matters when the moment has passed: WireMock's `stopRecording()` offers no second chance once a session is closed, whereas a snapshot can be taken whenever you decide you want one. Snapshot twice without clearing in between and you convert the same traffic twice.
go deeper
Know that both calls produce WireMock stub mappings, and that one is armed before the traffic while the other converts traffic that has already been served.
Explain why the snapshot form needs no target URL, and why calling it twice duplicates mappings while calling stopRecording twice does not.
Be ready to say which form you would put in a shared fixture and why, and how you keep a snapshot on a shared WireMock from converting another suite's traffic.
Own the standard: pick one form as the house default so captures are reproducible, and decide who may snapshot a server that several teams drive.
## Two directions on the same artefact WireMock gives you two ways to end up with stub mappings built from real traffic, and confusing them is the most common source of an empty or duplicated capture. They differ in one axis only: **when the decision to record is made relative to the traffic.** - WireMock's `startRecording(...)` is a *prospective* session. You decide first, then generate the traffic. WireMock proxies to the target you named and captures from that instant until `stopRecording()`. - WireMock's `snapshotRecord()` is a *retrospective* conversion. The traffic has already been served; the call turns what the server has kept about it into stub mappings. Nothing needs to have been armed in advance. Both hand back a WireMock `SnapshotRecordResult` and both register the resulting stubs on the running server, so downstream everything looks identical. The difference is entirely about which one you *could have* used. ## What the session form requires of you WireMock's `startRecording("https://kayaks.riverbend.example")` needs a target, because the session is what arranges the forwarding. Its constraints follow from that: - you must call it *before* the kayak-rental client makes the calls you want; - the window is bounded by WireMock's `stopRecording()`, and once that returns the window is gone; - the server is genuinely in a different mode for the duration, which WireMock's `getRecordingStatus()` will report as `Recording`. It is the right shape when a test fixture owns the whole interaction: arm, drive, stop, inspect. ## What the snapshot form requires of you WireMock's `snapshotRecord()` needs no target, because it is not arranging any forwarding — it is reading what the server has already served and converting it. Its constraints are the mirror image: - something must already have produced real exchanges through this WireMock, typically because a proxy arrangement was in place; - the conversion is not a consuming read, so calling it twice converts the same traffic twice and you end up with duplicate mappings; - it converts everything in scope, not just your test's calls, which on a shared server means somebody else's kayak-rental traffic lands in your set. ## Choosing between them | situation | reach for | |---|---| | A fixture that arms, drives and stops in one method | WireMock's `startRecording(...)` / `stopRecording()` | | A client already driven by hand through a browser | WireMock's `snapshotRecord()` | | A proxying server that has been running all morning | WireMock's `snapshotRecord()` | | A window you want explicitly bounded and observable | WireMock's `startRecording(...)` / `stopRecording()` | The practical rule is short: **if you have not decided yet, you still have the snapshot option; if you have decided in advance, the session gives you a cleaner boundary.** ## Shaping either one Both calls take the same specification object. In WireMock, `snapshotRecord(recordSpec()...)` and `startRecording(recordSpec()...)` are the fuller forms, and the spec is where you narrow what the conversion produces — which request headers become part of the recorded match, how large a body must be before it is extracted to a file, whether repeated identical requests are collapsed. On a snapshot this is not a nicety: because a snapshot converts everything in scope, the spec is often the only thing standing between you and a hundred mappings from a polling client. ## The three traps 1. **The double snapshot.** Two WireMock `snapshotRecord()` calls with nothing cleared between them produce the same mappings twice. The set silently doubles and the duplicates match identically, so nothing fails loudly. 2. **The empty snapshot.** If no real exchanges ever occurred — the client was answered by existing stubs, or never reached WireMock — the snapshot has nothing to convert and returns an empty result. The instinct is to blame the call; the cause is upstream of it. 3. **The borrowed traffic.** On a WireMock several suites drive, a snapshot cannot tell whose kayak-rental calls it is converting. It converts all of them. ## What neither one does Neither call cleans anything up. A recorded `rentalId`, a captured `Authorization` header and a frozen `availableFrom` timestamp are equally present whichever route you took, because both are converting the same real exchanges. Nor does either one decide where the mappings ultimately live or how a committed set is later regenerated — that is separate machinery with its own controls. The two calls in this question answer exactly one question between them: *given some real traffic, how do I turn it into WireMock stub mappings, and did I know in advance that I wanted to?* Mountebank has no equivalent of the retrospective form — an imposter either carries a `proxy` response that records as it serves, or it does not.
- In WireMock, why can snapshotRecord() produce more mappings than you expect on a shared server?Because it converts everything in scope, not just your test's traffic. On a WireMock several suites drive, another team's kayak-rental calls are converted alongside yours, and a second `snapshotRecord()` re-converts exchanges the first call already turned into mappings. Narrow it with `snapshotRecord(recordSpec()...)`, or snapshot a server nobody else is driving.
- Which of the two would you use when the client was driven by hand through a browser?In WireMock, `snapshotRecord()`, or `POST /__admin/recordings/snapshot`. The manual session is already over by the time you decide you want it, and the snapshot form is the only one of the two that can look backwards. `startRecording()` would have had to be called before the browsing began.
- Do the two forms produce different mappings from the same traffic?No. Both build WireMock stub mappings from real exchanges, both return a `SnapshotRecordResult`, and both register the stubs on the running server. They differ in when the decision to record is made, not in what the conversion produces, and both take the same WireMock `recordSpec()` to shape it.
startRecording is pressing record before the paddlers push off; snapshotRecord is pulling a clip out of a camera that was already rolling.
saying these in an interview costs you the question
- Thinks snapshotRecord() arranges the proxying itself
- Believes snapshotRecord() only works during a recording session
- Assumes a second snapshot skips already-converted traffic
- Expects snapshotRecord() to call the target itself
- Treats the two as producing different kinds of mapping