E2E测试中Global Guards/Filters/Interceptors未触发问题(GRPC场景)
全局守卫/拦截器/过滤器在NestJS E2E测试中不触发的解决办法
问题场景
运行时通过APP_GUARD、APP_INTERCEPTOR等方式注入的全局守卫、拦截器、过滤器能正常生效,但在E2E测试环境中完全不触发,只有给每个控制器手动本地指定这些增强器时才会工作。
核心原因
NestJS的Test.createTestingModule()创建的测试模块中,通过app = moduleFixture.createNestApplication()生成的是HTTP应用实例,而后续通过connectMicroservice添加的GRPC微服务是独立的实例。全局增强器默认只绑定到HTTP应用,不会自动同步到微服务实例上,导致测试中微服务接口无法触发全局守卫。
解决方案
方案1:给微服务实例手动绑定全局增强器
创建微服务后,直接给该实例调用useGlobalGuards、useGlobalInterceptors等方法,确保增强器绑定到微服务上。同时从测试模块中获取已注册的守卫实例,保持和运行时一致的依赖注入环境:
beforeAll(async () => { const moduleFixture = await Test.createTestingModule({ imports: [ AppModule, ClientsModule.register([ { name: '<name>', transport: Transport.GRPC, options: { url: 'localhost:5001', package: '<package>', protoPath: '<path>', credentials: GRPC.ChannelCredentials.createInsecure(), }, }, ]), ], }).compile(); app = moduleFixture.createNestApplication(); // 保存微服务实例 const microservice = app.connectMicroservice<MicroserviceOptions>({ transport: Transport.GRPC, options: { url: 'localhost:5001', package: SPEEDPHOTO_PACKAGE_NAME, protoPath: BOOTH_PROTO, }, }); // 从测试模块获取已注册的全局守卫,绑定到微服务 const authGuard = moduleFixture.get(AuthenticationGuard); microservice.useGlobalGuards(authGuard); // 绑定全局拦截器(如果需要) microservice.useGlobalInterceptors(new ExceptionInterceptor()); await app.startAllMicroservices(); await app.init(); const clientGrpc: ClientGrpc = microservice.get(BOOTH_SERVICE_NAME); client = clientGrpc.getService<BoothServiceClient>(BOOTH_SERVICE_NAME); });
方案2:在AppModule中统一配置微服务(推荐)
如果你的应用本身以GRPC微服务为核心,可在AppModule的bootstrap方法中直接创建微服务,这样测试时引入AppModule后,微服务实例会自动继承全局增强器配置:
修改AppModule的启动逻辑:
async function bootstrap() { const app = await NestFactory.create(AppModule); // 直接在启动时创建微服务 const microservice = app.connectMicroservice<MicroserviceOptions>({ transport: Transport.GRPC, options: { url: 'localhost:5001', package: SPEEDPHOTO_PACKAGE_NAME, protoPath: BOOTH_PROTO, }, }); await app.startAllMicroservices(); await app.listen(3000); // 若需同时提供HTTP服务可保留 } bootstrap();
简化后的测试代码:
beforeAll(async () => { const moduleFixture = await Test.createTestingModule({ imports: [AppModule], }).compile(); app = moduleFixture.createNestApplication(); await app.startAllMicroservices(); await app.init(); const microservice = app.getMicroservices()[0]; const clientGrpc: ClientGrpc = microservice.get(BOOTH_SERVICE_NAME); client = clientGrpc.getService<BoothServiceClient>(BOOTH_SERVICE_NAME); });
关键提示
- 全局增强器(通过
APP_*令牌注入的)是绑定到特定应用实例的,HTTP应用和GRPC微服务属于不同实例,需分别绑定。 - 优先使用从测试模块获取的增强器实例,避免手动new导致依赖注入环境不一致。
内容的提问来源于stack exchange,提问作者Herlin
相关产品推荐
相关产品推荐

