2

I have a core module that provides an authentication interceptor in Nest js. Here is the core module.

@Module({
    imports: [
    providers: [{
        provide: APP_INTERCEPTOR,
        useClass: LoggerInterceptor
    }
  ]
})
export class ConfModule {
}

This conf module is been imported by the app module.

@Module({
    imports: [
        ConfModule
    ]
})
export class AppModule {
}

Here is my LoggerInterceptor class

@Injectable()
export class LoggerInterceptor implements NestInterceptor {
    constructor(private readonly reflector: Reflector, private readonly connection: Connection) {
    }

    async intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
        // tslint:disable-next-line:no-console
        console.log(context.switchToHttp().getRequest().body);
        await this.connection.createEntityManager().save(context.switchToHttp().getRequest().body);
        return next.handle();
    }
}

I am currently writing an E2E test and will want to override the logger interceptor. Here is my MockLoggerInterceptor

export class MockLoggerInterceptor extends LoggerInterceptor {
    reflex: Reflector;
    conn: Connection;

    constructor(reflector: Reflector, connection: Connection) {
        super(reflector, connection);
        this.reflex = reflector;
        this.conn = connection;
    }

    // @ts-ignore
    async intercept(context: ExecutionContext, next: CallHandler): Observable<any> {
        // tslint:disable-next-line:no-console
        console.log(context.switchToHttp().getRequest().body);
        await this.conn.createEntityManager().save(context.switchToHttp().getRequest().body);
        return next.handle();
    }

}

Here is my test Suite

describe('PermissionController', () => {
    let applicationContext: INestApplication;
    let connection: Connection;
    let testUtils: TestUtils;
    let appHeader: App;

    beforeAll(async () => {
        const moduleRef: TestingModule = await Test.createTestingModule({
            imports: [AppModule]
        }).overrideInterceptor(LoggerInterceptor).useClass(MockLoggerInterceptor).compile();

        applicationContext = moduleRef.createNestApplication();
        connection = getConnection();
        await applicationContext.init();
        testUtils = new TestUtils(connection);
        appHeader = await testUtils.getAuthorisedApp();

    });
    it('Test of permission can be created', async () => {
        await request(applicationContext.getHttpServer())
            .post('/permissions')
            .set({
                'X-APP-CODE': appHeader.code,
                'X-APP-TOKEN': appHeader.token,
                'Authorisation': appHeader.token
            })
            .send(
                {
                    permissionName: 'newPermission'

                }
            ).expect(201);
    });

    afterAll(async () => {
        await connection.close();
        await applicationContext.close();

    });
});

My test still uses the conf module logger instead of the test logger. Apparently there are other use cases but this is the best I can give.

uncle-tee
  • 348
  • 4
  • 10
  • that's a limitation of using `APP_INTERCEPTOR`, see: https://github.com/nestjs/nest/issues/4053#issuecomment-585612462 – Micael Levi Jul 31 '23 at 14:14

1 Answers1

2

You have to use overrideInterceptor instead of overrideProvider, as an interceptor is not provided in the providers array of a module:

.overrideInterceptor(LoggerInterceptor).useClass(MockLoggerInterceptor)
Kim Kern
  • 54,283
  • 17
  • 197
  • 195
  • Thanks @Kim Kern apparently I did this. But it still did not work. I have tried all I can. I want to be sure before I raise this as an issue. – uncle-tee Feb 12 '20 at 16:00
  • Your `MockLoggerInterceptor` and `LoggerInterceptor` have the same behavior, don't they? How do you know which one is used? Does the mocking only fail for global interceptors? – Kim Kern Feb 13 '20 at 12:23