What does WireMock's GET /__admin/health tell a CI job waiting on a shared stub server?
answer
- up is not the same as ready
- a TCP accept proves less
- the admin surface answers first
- health is liveness, not content
- says nothing about whose stubs are loaded
basics
~20 sWireMock's GET /__admin/health answers 200 only once the admin API is serving, so a pipeline polls it rather than the TCP port. It proves the process is up. It does not prove your bakery pre-order mappings are loaded.
solid answer
~40 sOn a shared CI instance the stub server outlives every individual run, so a job's first problem is knowing whether it is answering at all. In WireMock the readiness probe is `GET /__admin/health`, served by the admin API under `/__admin` on the same port as the stubs; a pipeline normally polls it in a loop with a hard timeout before pointing any suite at the bakery pre-order stubs. A raw TCP connect is weaker, because a socket can accept while the server is still assembling itself. In MockServer the equivalent readiness call is `PUT /mockserver/status`, which reports the ports the instance is bound to. What neither call tells you is content: on a long-lived instance, health says the server is up, never that the mappings on it are the ones your run expects.
code
bash · 9 lines# Wait for the long-lived shared instance before pointing a suite at it
deadline=$((SECONDS + 60))
until curl -sf http://stubs.ci.internal:8080/__admin/health > /dev/null; do
[ $SECONDS -lt $deadline ] || { echo "stub server never became ready"; exit 1; }
sleep 1
done
# Liveness is settled; whose mappings are loaded is a separate question
curl -s http://stubs.ci.internal:8080/preorders/v1/orders/BP-4417go deeper
Be ready to say what a readiness check is: a call a job repeats until the server answers, before any test runs. Name WireMock's GET /__admin/health as the route that serves it.
Explain why the health route beats a TCP connect. A socket can accept while the server is still starting, so only a routed response proves the admin API is actually serving requests.
Show that you separate liveness from content. Describe the shared-instance failure where health is green, another team replaced your mappings minutes ago, and the suite fails looking like flake.
Own the readiness contract itself: what every consumer of the shared instance is promised, what the timeout and its failure message must say, and who is accountable when a green health check stops meaning anything.
## The shape this question lives in A **shared CI instance** is one stub-server process that outlives any single test run. It is started once, typically as a long-lived `wiremock/wiremock` container standing beside the pipeline, and every suite that needs the bakery pre-order API is pointed at the same host and port. Nothing about that arrangement starts the server at the moment your suite needs it, so the first thing a job has to establish is whether the instance is answering *right now*. WireMock's answer is a readiness route on its admin API: **`GET /__admin/health`**, served under `/__admin` on the same port that serves the stubs. ## What a successful health call establishes The health route is handled by WireMock's admin surface, so it can only answer once that surface is initialised and dispatching. A successful call therefore establishes three things: - the process is alive and has bound its listening port; - the HTTP stack is past start-up and routing requests rather than queueing them; - the admin API in particular is wired up, not merely the stub listener. The third point is what makes the round trip worth taking. A TCP-level check, such as a socket connect in a shell loop or a container port probe, can succeed during the window in which the server has bound the port but cannot yet answer anything. Polling `GET /__admin/health` closes that window, because a response can only come from a server already routing requests through its admin handler. ## What it deliberately does not establish Health is **liveness, not content**. It reports nothing about which mappings are loaded, who loaded them, or whether they are still present. On an instance created for a single run that distinction is academic, because nobody else could have touched it. On a long-lived shared instance it is the entire problem: between your readiness poll and your first assertion, another team's run can add, replace or remove mappings on the very same server. | what the job wants to know | does `GET /__admin/health` answer it? | |---|---| | Is the process up? | yes | | Is the admin API serving? | yes | | Are bakery pre-order mappings loaded at all? | no | | Are they the ones this run expects? | no | | Is another run using the instance concurrently? | no | Reading a green health check as *my stubs are ready* is the commonest mistake made against a shared instance, and it produces failures that read as flake: the suite starts, the stub it needs was replaced ninety seconds ago by somebody else's job, and the client under test receives an answer nobody wrote for it. ## Polling it like an operator 1. **Poll, do not sleep.** A fixed sleep is either wasted minutes or an unreliable guess; a loop that calls the health route every second until it answers, under one overall timeout, is neither. 2. **Treat every non-2xx and every connection error as not-ready** and keep polling until the deadline. A refused connection early in start-up is normal and expected. 3. **Fail loudly on timeout**, printing the address polled and the elapsed time. *Could not reach the shared stub server after 60s* is a diagnosable failure; a suite that starts anyway and emits a page of assertion errors is not. ## The same practice in the neighbouring product In MockServer the equivalent readiness call is **`PUT /mockserver/status`**, which reports the ports the instance is bound to; the shape of the practice is identical even though the verb, the path and the payload are not. ## Closing the gap that health leaves open Because readiness stops at liveness, a job on a shared instance needs a second, separate step to establish that the content it depends on is there. Keep the two apart: - **Readiness** is a property of the process, and it belongs in the wait loop. - **Content** is a property of the moment, and it belongs to the run: check it after the wait, immediately before the suite, and treat a mismatch as an environment failure rather than a test failure. - **Never encode healthy-therefore-correct** in a wait script. On a shared instance that implication is false by construction, and scripts outlive the person who wrote them. - **Record which address went green and when.** After an unexplained failure the first question is whether the run was even talking to the instance everyone assumed. The habit that survives contact with a real pipeline is simple. Health answers whether anything is there, and nothing else; every question about *whose* stubs are there is one your run has to ask on its own.
- How would you tell, at the start of a run, that the mappings on a shared instance are the ones you expect?Health cannot answer it, so the run has to ask separately. After the readiness wait, exercise one endpoint whose stubbed reply is distinctive to your fixture set, such as a known bakery pre-order reference returning the status your fixtures define, and treat a mismatch as an environment failure that stops the suite immediately rather than as a test assertion.
- What should the readiness loop do when its timeout expires?Fail the job, not the tests. Print the address polled, the elapsed time and the last connection error, then exit non-zero before any suite starts. A run that proceeds against an unreachable shared instance turns one infrastructure fault into a page of assertion failures nobody can attribute.
saying these in an interview costs you the question
- Treats a successful TCP connect to the port as proof the server is ready.
- Assumes a healthy WireMock instance means the run's own mappings are loaded.
- Uses a fixed sleep before the suite instead of polling with a timeout.
- Expects GET /__admin/health from MockServer, mixing the two products' readiness calls.
- Thinks a green health check means no other run is using the shared instance.