I'm writing E2E tests for my NestJS project and I bumped into one issue I could not solve.
This is my setup fragment
const moduleFixture: TestingModule = await Test.createTestingModule({
imports: [AppModule], // AppModule imports AuthModule
})
.overrideProvider(APP_GUARD) // Not working
.useClass(MockedAuthGuard)
.compile();
app = moduleFixture.createNestApplication<NestExpressApplication>();
The goal is to use MockedAuthGuard
instead of real AuthGuard
in my tests.
The problem is that it has no effect. It still hits a real class instead of my mock version.
What I tried is to modify my module like so
@Module({
imports: [],
providers: [
{
provide: APP_GUARD,
useClass: Env.isE2E ? MockedAuthGuard : AuthGuard,
},
],
})
export class AuthModule {}
And now it works, but I don't like this part Env.isE2E ? MockedAuthGuard : AuthGuard
. I want to keep it clean and only override it in E2E tests.
What am I missing here? How can I make it work by using overrideProvider
method?
Rather than using useClass
with theAPP_GUARD
provider, you can add the AuthGuard
to the providers
array directly, and then use useExisting: AuthGuard
for the APP_GUARD
provider. Then, in your tests you can properly use overrideProvider(AuthGuard).useClass(MockedAuthGuard)
without any issue, leaving your modules clean, and your tests the only ones referencing the mocks.
@Module({
imports: [],
providers: [
AuthGuard,
{
provide: APP_GUARD,
useExisting: AuthGuard,
},
],
})
export class AuthModule {}