Testing and Overrides
Use .override() when tests need to replace an existing registration with a mock.
function buildContainer() {
return new Container()
.registerClass('logger', ConsoleLogger, [])
.registerClass('db', PgDb, [])
.registerClass('users', UserRepo, ['logger', 'db'])
}
const c = buildContainer()
.override('logger', mockLogger)
.override('db', mockDb)The override value must be assignable to the original registered type. Missing keys and incompatible mocks are TypeScript errors.
Override Timing
Apply overrides before resolving the dependency graph:
const logger = c.get('logger')
c.override('logger', mockLogger)The second line throws because the singleton value is already cached on this container. The guard is deliberately cache-based: it also catches scoped values cached on the current scope, registerValue, and repeated overrides. Transient resolutions and ancestor-owned values resolved through a child are not cached locally, so they are not tracked. A previously returned transient remains with its caller while later resolves return the mock. Treat this as part of the contract, not permission for late overrides: applying every override before graph resolution avoids split graphs.
Ownership
Override values are externally owned. Like registerValue, an override is not added to the container's disposal queue. The test fixture owns its cleanup.
Scope Locality
An override mutates only the container it is called on:
const scope = root.createScope().override('db', mockDb)The root and sibling scopes are unchanged. Parent-level overrides are visible through the usual parent lookup.
