skip to content

Transport Conditions

Getting traffic to a stand-in server and making it misbehave on purpose: recording, selective pass-through, HTTPS, broken connections and delay. Most suites only ever stub a healthy, instant 200.

on this pageshow

explore

questions

22

In Mountebank, what do proxyOnce, proxyAlways and proxyTransparent each do to a proxied request?

level: juniorimportance: must knowfreq 64%

answer

  1. three modes on one proxy response
  2. they differ in what gets kept
  3. once: upstream sees each call once
  4. always forwards every matching request
  5. transparent never saves the reply

basics

~20 s

Mountebank's proxyOnce forwards the first matching glossary request to the real service and answers later identical ones from the saved reply. proxyAlways forwards every matching request upstream. proxyTransparent forwards everything and saves nothing, staying a pure pass-through.

solid answer

~50 s

All three are values of `mode` on a Mountebank `proxy` response, and they differ only in what the imposter does with the reply that comes back from the translation-glossary service. `proxyOnce` forwards a request that reaches the proxy stub, saves the upstream reply as a new stub keyed by the generated predicate, and answers every later request matching that predicate locally, so the real service sees each distinct call once. `proxyAlways` forwards every matching request upstream and accumulates the replies, which is what you want when the same call must return changing data. `proxyTransparent` forwards and returns without saving anything, so the imposter never stops being a pass-through. The mode is the whole of the choice: `to` decides where traffic goes, `mode` decides whether it keeps going there. In WireMock the equivalent broad mapping returns `aResponse().proxiedFrom("https://glossary.example.com")` and has no mode switch at all.

code

json · 19 lines
json
{
  "port": 4547,
  "protocol": "http",
  "stubs": [
    {
      "predicates": [
        { "equals": { "method": "GET", "path": "/v2/glossaries/marine-biology/terms" } }
      ],
      "responses": [
        { "is": { "statusCode": 200, "body": { "entries": [], "revision": 41 } } }
      ]
    },
    {
      "responses": [
        { "proxy": { "to": "https://glossary.example.com", "mode": "proxyTransparent" } }
      ]
    }
  ]
}

go deeper

for a junior

Be ready to name Mountebank's three proxy modes - proxyOnce, proxyAlways and proxyTransparent - and say in one sentence what each does with the reply that comes back from the real service.

for a middle

Explain that mode changes only what the imposter keeps, never which requests are forwarded, and show why proxyOnce quietly stops contacting the real service after the first call of each shape.

for a senior

Show that you pick the mode from the endpoint's behaviour: proxyTransparent when unfaked traffic must always be real, proxyAlways when the upstream answer legitimately moves between calls.

for a principal

Own the consequence across suites. A proxyTransparent imposter makes every run depend on a live third party, while proxyOnce trades that dependence for answers that silently age. Say which you would standardise on and what makes you revisit it.

## What a Mountebank `proxy` response actually is A Mountebank **imposter** is one process listening on one port, and its `stubs` array holds the rules it answers with. Each stub has `predicates` that decide whether it applies and `responses` that decide what comes back. A Mountebank response is one of four kinds: `is` (a canned reply you wrote), `inject` (JavaScript that builds a reply), `fault` (a broken connection instead of a reply), or `proxy` — and `proxy` is the one that does not answer at all. It forwards the request to the address in its `to` field, waits for the real translation-glossary service to answer, and hands that answer back to the caller unchanged. That forwarding is the second half of selective pass-through. The imposter holds specific stubs for the glossary paths you are faking — say one that answers `GET /v2/glossaries/marine-biology/terms` with a fixed list of entries — and one broad Mountebank `proxy` stub that carries everything the specific stubs did not answer out to the real service. `mode` is the field that decides what the imposter does with each reply that comes back through that proxy stub. ## The three Mountebank modes, side by side | Mountebank `mode` | forwards | keeps the reply | what upstream sees | |---|---|---|---| | `proxyOnce` | until a saved reply exists | yes | each distinct request once | | `proxyAlways` | every matching request | yes, appended | every request | | `proxyTransparent` | every matching request | no | every request | - Mountebank's **`proxyOnce`** forwards the request, saves the upstream reply as a new stub, and answers every later request that the saved stub's predicate accepts from that saved copy. The real glossary service is contacted once per distinct request shape and then goes quiet for the rest of the run. - Mountebank's **`proxyAlways`** forwards every matching request upstream and appends each reply to the saved stub, so the proxy keeps firing instead of being short-circuited. This is the mode for an endpoint whose answer legitimately changes — a `revision` counter, a remaining-quota field — because the imposter never starts answering from a stale copy. - Mountebank's **`proxyTransparent`** forwards and returns and saves nothing at all. The imposter is a pure conduit for that traffic for as long as it runs, which is what selective pass-through usually wants: the glossary paths you faked stay faked, and everything else genuinely reaches the real service every single time. ## What the mode does not control This is where the field is most often misread. All three Mountebank modes forward. The mode is a decision about the *reply*, not about the *request*: - It does not decide **which** requests reach the proxy stub — that stub's own `predicates`, or their absence, decide that. - It does not decide **where** they go; Mountebank's `to` does. - It does not change the request on the way out; Mountebank's `injectHeaders` does that. - It does not decide what a saved stub keys on; Mountebank's `predicateGenerators` does, and with no generators the saved stub carries no predicates at all. - It does not touch the reply's status code, headers or body. The client sees exactly what the glossary service sent. ## Choosing one for a real suite 1. If the point of the proxy is that unfaked traffic must always be real — the usual reason a broad proxy sits under specific stubs — choose Mountebank's `proxyTransparent`. Nothing accumulates, nothing goes stale, and the arrangement means the same thing on the tenth request as on the first. 2. If you want the first call to be real and the rest to be fast and offline, choose Mountebank's `proxyOnce`, and then take `predicateGenerators` seriously, because that generated predicate is what decides whether the second call counts as the same request. 3. If the endpoint's answer moves between calls and you still want every exchange to reach the real service, choose Mountebank's `proxyAlways`. ## The failure each mode produces Every mode buys something and charges for it, and naming the charge is what an interviewer is listening for. - `proxyOnce` fails by going quiet: a suite that was exercising the real translation-glossary service stops doing so after the first call of each shape, and a change upstream no longer shows up anywhere. - `proxyAlways` fails by volume: replies accumulate on the saved stub for the life of the imposter, and a long run leaves a pile nobody reads. - `proxyTransparent` fails by dependence: every run needs the real glossary service reachable and credentialled, so an outage there is an outage in your pipeline. None of those is a bug. Each is the price of the mode you chose, and the choice is a single string in the imposter definition.

  • Which Mountebank proxy mode fits a glossary endpoint whose revision counter changes on every call?
    `proxyTransparent` if you only want the live answer, `proxyAlways` if you also want each exchange kept. Both forward every matching request, so the client always sees the current revision. `proxyOnce` is wrong here: it saves the first reply and answers from it afterwards, which pins the counter at whatever value the first call happened to return.
  • What does the `to` field on a Mountebank proxy response accept, and how is the path decided?
    `to` takes the base address of the real service, such as `https://glossary.example.com`. Mountebank forwards the incoming request to that address, so the path and query the client sent are what the upstream receives. If the imposter must reach a different path than the client asked for, that is a different `to` or a different stub, not a `mode` setting.

saying these in an interview costs you the question

  • Thinking proxyOnce forwards only one request in total
  • Calling proxyTransparent a recording mode
  • Believing the mode decides which requests reach the proxy stub
  • Assuming proxyAlways overwrites the previous saved reply
  • Expecting the mode to change the reply the client sees
open as a page

How do you start WireMock standalone so it records the kayak-rental API into stub mappings?

level: juniorimportance: must knowfreq 68%

basics

~20 s

Run WireMock standalone with --record-mappings and --proxy-all pointed at the kayak-rental base URL. Every request is forwarded upstream and the real reply is written back as a stub mapping. Large response bodies are extracted into separate body files.

open as a page

In WireMock, what do startRecording() and stopRecording() do to kayak-rental traffic?

level: juniorimportance: must knowfreq 61%

basics

~20 s

In WireMock, startRecording puts the running server into recording mode against a target base URL. WireMock's stopRecording ends the session and returns a SnapshotRecordResult holding the stub mappings built from the traffic. Both are also WireMock admin routes.

open as a page

What does WireMock serve at GET /__admin/certs/wiremock-ca.crt, and who needs it?

level: juniorimportance: must knowfreq 55%

basics

~20 s

It serves the public CA certificate WireMock signs browser-proxy certificates with. A client proxied through WireMock must install it in its trust store, or the call fails before any stub is matched. The private key stays on the server.

open as a page

In WireMock, what do --https-port, --https-keystore and --keystore-password do?

level: juniorimportance: must knowfreq 64%

basics

~20 s

WireMock's --https-port opens an extra TLS listener on that port. --https-keystore points at a Java keystore holding the certificate WireMock presents there, and --keystore-password unlocks it. Omit both and WireMock serves its own bundled self-signed certificate instead.

open as a page

In MockServer, what does error().withDropConnection(true) do to a cattle-auction bid client?

level: middleimportance: must knowfreq 68%

basics

~20 s

The client gets no status line, no headers and no body. MockServer tears the socket down instead of replying, so the bid call fails as an IO error. That is a client branch no HTTP status code can reach.

open as a page

In WireMock, what does --enable-browser-proxying change about how a client reaches your stubs?

level: middleimportance: must knowfreq 57%

basics

~20 s

It turns WireMock into a forward proxy. Rather than dialling WireMock's base URL, the client keeps requesting the real target host and routes it through WireMock. For HTTPS, WireMock terminates the tunnel with a certificate it mints for that host.

open as a page

In MockServer, what does connectionOptions().withCloseSocket(true) do to a bid reply?

level: juniorimportance: should knowfreq 50%

basics

~20 s

The reply is still written in full. MockServer then closes the socket rather than leaving it open for reuse. withCloseSocket is one of ConnectionOptions' eight settings, and it attaches to an HttpResponse, never to an error action.

open as a page

In WireMock, which four Fault values can withFault() take, and what does each do?

level: juniorimportance: should knowfreq 62%

basics

~20 s

WireMock's Fault enum has exactly four values: EMPTY_RESPONSE, CONNECTION_RESET_BY_PEER, MALFORMED_RESPONSE_CHUNK and RANDOM_DATA_THEN_CLOSE. You pass one to WireMock's aResponse().withFault(...) instead of a status code. Each breaks the reply below the HTTP layer rather than returning an error code.

open as a page

In Mountebank, what is the fault response type, and which two values does it take?

level: middleimportance: should knowfreq 44%

basics

~20 s

Mountebank's fault is a response type used instead of is, proxy or inject, and it takes exactly two values: CONNECTION_RESET_BY_PEER and RANDOM_DATA_THEN_CLOSE. Both are spelled like WireMock constants but belong to Mountebank. It is not one of Mountebank's five behaviors.

open as a page

In WireMock, how do withFixedDelay(), withUniformRandomDelay() and withLogNormalRandomDelay() differ?

level: middleimportance: should knowfreq 64%

basics

~20 s

WireMock's withFixedDelay holds every matching reply for the same number of milliseconds. WireMock's withUniformRandomDelay samples each pause evenly between a lower and upper bound. WireMock's withLogNormalRandomDelay samples around a median, where a bigger sigma lengthens the slow tail.

open as a page

In Mountebank, what does injectHeaders do to a request passing through a proxy?

level: middleimportance: should knowfreq 46%

basics

~20 s

Mountebank's injectHeaders adds headers to the request the proxy sends upstream, not to the one the client sent. It carries credentials or negotiation the code under test cannot supply, and it never affects matching or the reply the client receives.

open as a page

In Mountebank, what does predicateGenerators control on a proxy response?

level: middleimportance: should knowfreq 52%

basics

~20 s

Mountebank's predicateGenerators decides which fields of the forwarded request are copied into the predicate on the stub a proxy saves. Set method, path and the query fields that matter; omit it entirely and the saved stub matches everything.

open as a page

In Mountebank, what do recordRequests, mb save and mb replay do with kayak-rental traffic?

level: middleimportance: should knowfreq 49%

basics

~20 s

In Mountebank, recordRequests makes an imposter keep every request it receives, and a proxy response saves the real replies as new stubs. mb save writes that configuration to a file; mb replay strips the proxies so recorded stubs answer.

open as a page

In WireMock, how does snapshotRecord() differ from a startRecording() session for kayak-rental traffic?

level: middleimportance: should knowfreq 54%

basics

~20 s

In 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.

open as a page

In MockServer, which class carries withDropConnection, and why is it not on ConnectionOptions?

level: seniorimportance: should knowfreq 48%

basics

~20 s

MockServer puts withDropConnection(Boolean) on HttpError, the terminal error action that replaces a reply entirely, not on ConnectionOptions. ConnectionOptions decorates a real response, and its connection-breaking switch is withCloseSocket(true). The probability variant, withDropConnectionProbability(Double), is on neither class: it lives on HttpChaosProfile.

open as a page

In WireMock, what does withChunkedDribbleDelay() do to a reply that withFixedDelay() does not?

level: seniorimportance: should knowfreq 56%

basics

~20 s

WireMock's withFixedDelay writes nothing until the pause elapses, then sends the whole reply at once. WireMock's withChunkedDribbleDelay sends the status line and headers immediately and spreads only the body across the stated duration, in the requested number of slices.

open as a page

Why can a Mountebank imposter silently send glossary traffic to the real service instead of its own stub?

level: seniorimportance: should knowfreq 50%

basics

~20 s

A broad Mountebank proxy stub takes every request the specific stubs did not match, so a predicate that grew too tight does not fail loudly. The call is forwarded to the real glossary service and the test still passes.

open as a page

How would you standardise what a WireMock recording of the kayak-rental API is allowed to capture?

level: principalimportance: should knowfreq 44%

basics

~20 s

Fix the capture shape in one place: a shared WireMock record spec naming which request headers are captured, which bodies are extracted to files, and how repeats are handled. Then require that recorded mappings are read before anything is committed.

open as a page

How would you govern WireMock's browser-proxy CA and --trust-all-proxy-targets across many suites?

level: principalimportance: should knowfreq 41%

basics

~20 s

Decide who mints the CA. Either every WireMock generates its own and each job fetches GET /__admin/certs/wiremock-ca.crt into a job-scoped trust store, or one pinned --ca-keystore is shared and its signing key becomes a secret you must own and rotate.

open as a page

In Mountebank, which behavior makes a stubbed response slow, and how is it declared?

level: middleimportance: nice to knowfreq 47%

basics

~20 s

Mountebank's wait behavior makes a response slow. It is one of Mountebank's five behaviors and is declared as an entry in the behaviors array on a response, taking a number of milliseconds. Repeat is not a behavior.

open as a page

In WireMock, when should injected delay live in setGlobalFixedDelay() rather than on each stub?

level: principalimportance: nice to knowfreq 44%

basics

~20 s

WireMock's setGlobalFixedDelay writes the delay into the server's settings store. It applies to every stubbed reply and appears in no mapping file. WireMock's per-stub withFixedDelay serialises into the mapping and replaces the global figure rather than adding to it.

open as a page