To replace a dependency in a NestJS test, build the module with Test.createTestingModule(), chain .overrideProvider(Token).useValue(double) (or useClass / useFactory), then await compile() and fetch your subject with get(). Overrides must be declared before compile(). This guide gives a copyable cheat sheet first, then the edge cases that usually explain why an override seems to be ignored.
Cheat sheet: override a provider and get the controller
This is an illustrative pattern adapted from the API shape in the NestJS Testing documentation; it is not output from a test run. Swap vi.fn() for your runner’s mock function (for example jest.fn()). The Nest testing APIs are runner-agnostic: the docs say, “You can use any testing framework you like, because Nest doesn’t force any specific tooling.” The current guide notes that newly generated projects use Vitest by default, but overrideProvider() does not require it.
import { Test } from '@nestjs/testing';
import { CatsService } from './cats.service';
import { CatsController } from './cats.controller';
describe('CatsController', () => {
let controller: CatsController;
const catsServiceMock = {
findAll: vi.fn().mockReturnValue(['test-cat']),
};
beforeEach(async () => {
const moduleRef = await Test.createTestingModule({
controllers: [CatsController],
providers: [CatsService],
})
.overrideProvider(CatsService)
.useValue(catsServiceMock)
.compile();
controller = moduleRef.get(CatsController);
});
});
The sequence is always the same:
Test.createTestingModule(metadata)takes module metadata and returns aTestingModuleBuilder.- Chain override calls on the builder. They are chainable.
await compile()instantiates and initializes the testing module. It is asynchronous.- Retrieve the subject with
get()(static providers and controllers) orresolve()(scoped or transient providers).
Which override method to use
| Target | Builder call | Replacement method | Use it when |
|---|---|---|---|
| Provider | overrideProvider(token) |
useValue, useClass, useFactory |
You need a controlled dependency or test implementation. |
| Guard | overrideGuard(guard) |
useValue, useClass, useFactory |
A route or application guard should behave differently in the test. |
| Interceptor | overrideInterceptor(interceptor) |
useValue, useClass, useFactory |
Interceptor behavior should be replaced. |
| Filter | overrideFilter(filter) |
useValue, useClass, useFactory |
Exception handling should be replaced. |
| Pipe | overridePipe(pipe) |
useValue, useClass, useFactory |
Transformation or validation should be replaced. |
| Module | overrideModule(module) |
useModule(replacementModule) |
A whole imported module should be substituted. |
Choosing value, class, or factory
useValue: a fixed object
You supply the instance yourself. This is the simplest choice for a hand-written object or a bag of mock functions whose calls you want to assert on, as in the cheat sheet.
useClass: a class Nest instantiates
You supply a class and Nest creates it, so the replacement can have its own constructor dependencies resolved from the testing module. Use it for a reusable fake implementation (an in-memory repository, say).
Free tools Windows power users keep installed
One-click scans. No signup required.
#1 Best Overall
useFactory: a function that returns the replacement
You supply a function that produces the object. Choose it when construction needs logic, such as building a different double per scenario.
Whole modules: useModule
Module overrides are the exception to the three-style rule. Use overrideModule(DatabaseModule).useModule(FakeDatabaseModule) to swap an entire imported module rather than individual providers.
Why an override seems not to work
The override comes after compile()
Overrides belong on the builder. Once compile() has run, the graph is instantiated; configure everything first, and call compile() last.
A global enhancer is registered with APP_GUARD and useClass
When a guard is registered globally via APP_GUARD with useClass, the implementation may not be exposed as a normal provider token for an override to target. The NestJS guide’s remedy is to register with useExisting and list the implementation class as a provider too, then override that class. The guide applies the same consideration to globally registered guards, pipes, interceptors, and filters. The shape below follows that documented pattern; check it against your own module metadata.
Quick wins for a faster PC:
Fix the driver behind crashes, sound loss and screen glitchesFind Drivers →Clear out junk files and repair common Windows errorsFree Scan →Scan for outdated or missing drivers - takes under a minuteDriver Scan →Rank #3
providers: [
{
provide: APP_GUARD,
useExisting: JwtAuthGuard,
},
JwtAuthGuard,
]
Then apply .overrideProvider(JwtAuthGuard).useValue(mockGuard) (or another supported replacement) before .compile(). The fix is in how the production module registers the enhancer; a test-side override alone may not reach an inaccessible token.
You used get() on a scoped provider
get() retrieves static instances. For request-scoped or transient providers, use await moduleRef.resolve(Token). The docs warn that resolve() returns an instance from a DI sub-tree with its own context identifier, so calling it twice does not guarantee the same object reference. If you need the same instance across calls, that is a matter of how you manage the context in the test, not something resolve() promises.
Rank #4
Expecting an e2e test to behave like a unit test
An override controls dependency wiring; it does not change the scope of the test. The official e2e example imports the application module, applies .overrideProvider(CatsService).useValue(catsService), compiles, creates a Nest application, initializes it, and sends HTTP requests with Supertest. Everything else in that module graph is still real. For an isolated test, declare a small module with just the controller or service under test, as in the cheat sheet.
HttpAdapterHost#httpAdapter is undefined
After compile() alone, no HTTP adapter or server exists, so HttpAdapterHost#httpAdapter is undefined. The documentation’s guidance is to use createNestApplication() where appropriate, or to refactor code that depends on the adapter at initialization time.
Best Value
Picking a pattern: four questions
- Granularity: one provider, one enhancer, or a whole module?
- Shape: a fixed object (
useValue), a class Nest builds (useClass), or a factory result (useFactory)? - Scope of test: isolated component module, or application-level e2e with
createNestApplication()? - Provider scope: static (
get()) or request-scoped/transient (resolve())?
None of these is universally best; they follow from what the test must prove.
Version caveat
The NestJS testing guide is a rolling document, and its examples and default runner may change. This article does not tie these patterns to a specific Nest major version, so confirm against the documentation for the version you run.
Quick Recap
Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.




