Which call adds a stub to a running Mountebank imposter, and what does WireMock use instead?
answer
- three products, three control planes
- the imposter is the unit
- a port in the path, not a name
- Mountebank: POST /imposters/:port/stubs
- PUT there replaces the whole list
basics
~20 sIn Mountebank, POST /imposters/:port/stubs adds one stub to an imposter that is already listening, and PUT on that path replaces its whole stub list. WireMock has no imposter object: it registers mappings with POST /__admin/mappings.
solid answer
~40 sMountebank's control plane is the imposter resource under `/imposters`, and Mountebank addresses an imposter by the port it listens on. `POST /imposters/:port/stubs` adds a stub to the list that Mountebank imposter already holds; `PUT /imposters/:port/stubs` replaces its whole list in one call, so choosing the wrong verb silently discards stubs an earlier step installed. WireMock's model is flatter: one server, one registered set of stub mappings, so WireMock's `POST /__admin/mappings` adds one and its `DELETE /__admin/mappings` clears them all. There is a structural difference behind the paths, too — Mountebank runs its control plane on mb's own port while each imposter serves stubbed traffic on its own, whereas WireMock serves `/__admin` on the same port as the stubs it answers. The names are the trap, and `/__admin` is WireMock's alone.
go deeper
Know that Mountebank configures an imposter through /imposters and WireMock configures a server through /__admin/mappings. Not mixing the two prefixes up is most of the value here.
Explain the model behind the paths: Mountebank's unit is an imposter identified by its port, WireMock's is a mapping identified by an id, and POST versus PUT on the stubs sub-resource differ in blast radius.
Show that you notice the structural consequence — Mountebank splits control and stubbed traffic across ports, WireMock shares one — because it changes what a suite must know to reach the control plane at all.
Own the standardisation call when teams run more than one stub server: whether helpers wrap each product's control plane behind one internal interface, and what that abstraction hides when someone has to debug it.
## Three products, three control planes The hardest thing about run-time stub administration is not any one product's routes; it is that three products solve the same problem on three unrelated surfaces, using the same English words for the pieces. WireMock, MockServer and Mountebank each have "stubs", a "proxy" and a "reset", and no two of them share a control path. The vocabulary transfers; nothing else does. | product | control-plane entry point | unit it registers | |---|---|---| | WireMock | `/__admin/mappings` | a stub mapping on the server | | Mountebank | `/imposters/:port/stubs` | a stub on one imposter | | MockServer | `PUT /mockserver/expectation` | an expectation on the server | Knowing which prefix belongs to which product is not trivia. A control call sent to a path the running product does not serve configures nothing at all, and because it fails quietly rather than loudly, the resulting "my stub never registered" hunt is one of the most common wasted afternoons on this subject. ## Mountebank's unit of configuration is the imposter Mountebank does not model "a server with stubs". It models **imposters**: in Mountebank, each imposter is a protocol server that listens on its own port and holds its own stub list. Mountebank's control plane lives under `/imposters` on mb's own port, and it addresses each imposter by the port that imposter listens on — which is why Mountebank's path carries a port where WireMock's `/__admin/mappings/{id}` carries a mapping id. That produces a genuine structural difference worth being able to state: - In Mountebank, admin traffic and stubbed traffic are on **different ports**: mb's port for control, the imposter's port for the fake upstream. - In WireMock, admin traffic and stubbed traffic share **one port**, with the `/__admin` prefix reserved on it. - Mountebank's control plane manages a **set of protocol servers**; WireMock's `/__admin/mappings` manages one server's **set of mappings**. - In Mountebank, creating configuration can mean creating a server: `POST /imposters` brings an imposter into existence, because the imposter is the thing that owns a port. ## POST versus PUT on Mountebank's stubs sub-resource On a Mountebank imposter that is already listening, the two verbs on the stubs sub-resource differ in blast radius, and that difference is the practical content of this question: - **`POST /imposters/:port/stubs`** adds a stub to the list that Mountebank imposter already holds, leaving the stubs already there in place. This is the call for "one more rule on a lighthouse imposter that is already serving". - **`PUT /imposters/:port/stubs`** replaces that Mountebank imposter's whole stub list with the one you send, so anything previously added is gone. This is the call for "the imposter should now hold exactly these rules and nothing else". Getting these the wrong way round is a quiet failure rather than an error. In Mountebank, using PUT when you meant to append silently discards the stubs a previous step installed, and the case that depended on them fails later with a lighthouse request that matches nothing. ## What WireMock does instead WireMock has no imposter object at all. A WireMock server is one server with one registered set of stub mappings, so in WireMock the equivalent operations all live on the `/__admin/mappings` collection: 1. WireMock's `POST /__admin/mappings` adds one mapping, which is the counterpart of the Mountebank append above. 2. WireMock's `DELETE /__admin/mappings` empties the set, the closest thing WireMock has to a wholesale list swap — though it clears rather than replaces. 3. WireMock's `POST /__admin/mappings/import` loads a document of many mappings in one call. 4. WireMock's `PUT /__admin/mappings/{id}` and `DELETE /__admin/mappings/{id}` address a single mapping by the id WireMock assigned it, an addressing model Mountebank's port-keyed path has no exact twin for. So the two surfaces do not map one to one, and pretending they do produces the errors below. ## The mistakes this asymmetry causes - Sending a stub definition to a path the running product does not serve, then concluding the stub "did not take" rather than that the call went nowhere. - Assuming a Mountebank imposter can be reconfigured on the port it serves stubbed traffic on, when Mountebank answers control calls on mb's own port. - Using Mountebank's `PUT /imposters/:port/stubs` to add one rule and silently losing the rest of that imposter's list. - Expecting a per-stub id back from Mountebank because WireMock hands one back, when Mountebank's path identifies the imposter rather than the stub. - Writing a shared helper called "add a stub" that works against one product only, without naming that product anywhere in its signature or its docs. - Copying an admin call out of one team's fixture into another's, where a different stub server is running. ## The rule to carry away Name the product in every sentence that names a path. `/__admin/mappings` is WireMock's; `/imposters/:port/stubs` is Mountebank's; each is meaningless to the other product, and neither is a synonym for the other's behaviour. Within Mountebank, POST on the stubs sub-resource appends to an imposter that is already listening, and PUT on the same sub-resource replaces that imposter's list outright. Within WireMock, `POST /__admin/mappings` adds one mapping to a flat registered set that WireMock's collection-level `DELETE` can empty. Both products let you reconfigure a stub server while it is running, which is the shared idea worth carrying between them — but no path, verb or unit of configuration transfers by guessing.
- Why can WireMock reconfigure itself on the same port while Mountebank cannot?WireMock reserves the `/__admin` prefix on the server that also answers stubbed traffic, so a control call is just a request to a reserved path. Mountebank's imposters are protocol servers that own their ports outright, so its control plane lives on mb's own port and addresses each imposter by the port it listens on.
- What does PUT /imposters/:port/stubs do that POST on the same path does not?It replaces the imposter's entire stub list with the one you send, so anything previously added is gone. POST adds a stub to the list the imposter already holds. The two differ in blast radius — the same distinction WireMock draws between `DELETE /__admin/mappings` and `DELETE /__admin/mappings/{id}`.
saying these in an interview costs you the question
- Calls /__admin against a Mountebank imposter
- Thinks all three products share one admin path
- Uses PUT /imposters/:port/stubs to add a single stub
- Addresses a Mountebank imposter by name rather than port
- Assumes Mountebank's control plane is on the imposter's port