How does an active test profile make a booted application resolve a fake dependency instead of the real one?
answer
- a named mode, then conditions on it
- swap the implementation or re-point the target
- one candidate beats a precedence rule
- a profile that never activated is silent
basics
~20 sA profile is a named run mode that gates registrations. Under it the fake's registration is a candidate and the real one is conditioned out, so the graph builds with the fake — provided the run truly activated that profile.
solid answer
~50 sA profile names a mode a run can be started in, and registrations can be conditioned on it: one implementation is contributed only when the test profile is active, the production one only when it is not. The container then has exactly one candidate for that boundary and builds the graph with the fake. The second lever is the same registration pointed at different settings — the address and credentials of a disposable instance rather than the production one — which swaps the *target* without swapping the implementation. Two failure modes dominate: nothing activated the profile, so the default registration quietly won and the test talked to the real thing; and both candidates stayed eligible, so the container either reports an ambiguous dependency or picks by a precedence rule (explicit over defaulted, more specific over general) that nobody in the room remembers.
go deeper
A profile is only a label; what does the work is registrations and settings conditioned on that label. Know how your run turns the mode on, because a mode that is never activated changes nothing.
Explain the two levers separately — conditioning which implementation is a candidate, and conditioning the values one implementation reads — and describe how the container settles a boundary with more than one candidate.
Show how you make the selection observable: a canary assertion on what actually resolved, mutual exclusion instead of precedence rules, and one tier that boots without the test mode so the production arrangement is exercised.
Own the drift question. Decide how much the test mode may diverge before it is a second application configuration, and who reviews additions to it against the production graph.
## What a profile is A **profile** is a named mode a run can be started in — conceptually a label attached to the process, chosen by the harness, an environment value, or a declaration on the test class. On its own a profile does nothing. Its power comes from registrations and settings being **conditioned** on it. Two distinct levers hang off that condition, and mixing them up is the usual source of confusion: | lever | what changes | typical use | |---|---|---| | conditioned registration | which implementation is a candidate for a boundary | bind a boundary to a fake that answers in process | | conditioned settings | the values the same implementation reads | point the real client at a disposable instance started for the run | The first swaps the *implementation*; the second swaps the *target*. A suite usually needs both: an in-process fake for the dependency you cannot start, and a real client aimed at a throwaway instance for the one you can. ## How the winner is chosen Once more than one registration could satisfy a boundary, something has to decide. The shapes seen across frameworks are: - **Mutual exclusion.** The real registration is conditioned to be absent under the test profile, so there is only ever one candidate. This is the least surprising arrangement and the one to prefer. - **Explicit beats defaulted.** A registration marked as a fallback yields to any other candidate; the fake is simply a non-fallback candidate. - **Specific beats general.** A candidate qualified by a profile outranks one that applies unconditionally. - **Last contribution wins.** The set is merged in a defined order and later sources replace earlier ones. - **Ambiguity is an error.** With two equal candidates and no rule to separate them, the container refuses to build and reports the conflict at startup. That last row is a feature, not an obstacle: a loud failure at boot is far better than a graph that silently chose the production implementation for a test run. ## The failure modes worth naming 1. **The profile was never activated.** The declaration existed, nothing turned it on for this run, every conditioned registration stayed out, and the default graph was built. The test then exercises the real dependency — slowly, or destructively — while appearing to pass. 2. **Both candidates stayed eligible.** Either the boot fails with an ambiguity, or a precedence rule nobody remembers resolves it, and which one it picked is not visible from the test. 3. **Half a swap.** The implementation was replaced but the settings still name the production target, or the reverse: the real implementation reads test settings and points somewhere harmless while the test believes it is talking to a fake. 4. **Profile creep.** The test profile accumulates registrations over years until it is a second application that resembles production only loosely, and a boot under it proves little about a boot under production settings. ## Making the choice visible Because every one of those failures is silent from inside a passing test, worthwhile suites make the wiring observable: - assert, once, that the boundary resolved to the type the run intended — a cheap canary that fails loudly when a profile stops being activated; - log or assert the active profile at the start of a run, so "which mode was this?" is answerable after the fact; - prefer mutual exclusion over precedence, so the question never needs a rule to settle it; - keep one high-fidelity tier that boots without the test profile at all, so the production arrangement is exercised somewhere. ## Keeping the two modes comparable A mode earns its keep only while the test arrangement stays a small, readable delta from the production one. Write conditioned registrations next to the ones they displace rather than in a distant file, keep the count small enough to read in one sitting, and re-examine long-lived entries: a fake added because a dependency was once slow may now be standing in for something perfectly cheap to start for real. The delta is the artefact to review, not the individual entry. ## What interviewers listen for The weak answer says "we set a profile and it uses the fake" and stops — a description of the outcome that never explains the selection. The answer they want names the mechanism (registrations conditioned on a named mode), separates swapping the implementation from re-pointing the settings, and volunteers the failure mode: if the profile is not actually active, the default wins and the test quietly runs against the real thing.
- How would you catch a run where the test profile was never activated?Assert the wiring, not just the response: one cheap check that the boundary resolved to the stand-in type the run intended, or that a value only the fake produces came back. Reporting the active mode at the start of the run helps too. Otherwise the default graph builds and the suite passes while talking to the real dependency.
- When is re-pointing settings preferable to binding the boundary to a fake?When you want the real client code in the path — its serialization, timeouts, retries and error mapping — and only the target should change. Binding to a fake removes that code from the evidence. Re-pointing keeps it and costs a disposable instance for the run.
- Two candidates satisfy the same boundary and the boot fails with an ambiguity. Is that a problem to work around?No — it is the arrangement failing loudly, which is what you want. Fix it by conditioning the candidates to be mutually exclusive so exactly one applies per mode, rather than by adding a precedence marker that makes the choice depend on a rule no reader of the test will recall.
saying these in an interview costs you the question
- Thinks naming a profile swaps implementations without any registration conditioned on it
- Cannot distinguish swapping the implementation from re-pointing its settings
- Assumes an unactivated profile fails loudly rather than building the default graph
- Treats an ambiguous-candidate startup error as tooling noise to suppress
- Lets the test mode accumulate registrations until it no longer resembles production