NestJS E2E测试覆盖Provider时依赖注入失效问题排查
问题:NestJS E2E测试中依赖注入失效,控制器内CatsService为undefined
错误日志
stdout | src/resources/cats/cat.spec.ts > Cats beforeAll stdout | src/resources/cats/cat.spec.ts > Cats app initialized stdout | src/resources/cats/cat.spec.ts > Cats > /GET cats catsService undefined [Nest] 34132 - 09/29/2025, 5:41:37 PM ERROR [ExceptionsHandler] Cannot read properties of undefined (reading 'findOne') TypeError: Cannot read properties of undefined (reading 'findOne') at CatsController.findOne (/Users/user/code/dvmonorepo/apps/backend/src/resources/cats/cat.controller.ts:16:29)
相关代码
CatsModule
import { Module } from '@nestjs/common'; import { CatsService } from './cat.service'; import { CatsController } from './cat.controller'; @Module({ controllers: [CatsController], providers: [CatsService], exports: [CatsService], }) export class CatsModule {}
CatsController
import { Controller, Get } from '@nestjs/common'; import { CatsService } from './cat.service'; @Controller('cats') export class CatsController { constructor( private readonly catsService: CatsService, ) {} @Get(':catId') findOne() { console.log('catsService', this.catsService); return this.catsService.findOne('1'); } }
CatsService
import { Injectable } from '@nestjs/common'; @Injectable() export class CatsService { constructor() {} async findOne(id: string) { return { id, email: 'cat@test.com', name: 'Test Cat' } } }
测试代码
import request from 'supertest'; import { Test } from '@nestjs/testing'; import { CatsModule } from './cat.module'; import { CatsService } from './cat.service'; import { INestApplication } from '@nestjs/common'; describe('Cats', () => { let app: INestApplication; let catsService = { findOne: () => ['test'] }; beforeAll(async () => { console.log('beforeAll'); const moduleRef = await Test.createTestingModule({ imports: [CatsModule], }) .overrideProvider(CatsService) .useValue(catsService) .compile(); app = moduleRef.createNestApplication(); await app.init(); console.log('app initialized'); }); it(`/GET cats`, () => { return request(app.getHttpServer()) .get('/cats/1') .expect(200) .expect({ data: catsService.findOne(), }); }); afterAll(async () => { await app.close(); }); });
解决方案
问题核心是控制器的findOne方法作为普通函数,在NestJS处理HTTP请求时丢失了this上下文,导致无法访问注入的catsService。可以通过以下两种方式修复:
方式1:将控制器方法改为箭头函数
箭头函数会自动绑定当前类实例的this,避免上下文丢失:
@Controller('cats') export class CatsController { constructor( private readonly catsService: CatsService, ) {} @Get(':catId') findOne = () => { console.log('catsService', this.catsService); return this.catsService.findOne('1'); } }
方式2:在构造函数中手动绑定this
通过bind方法手动将方法的this绑定到控制器实例:
@Controller('cats') export class CatsController { constructor( private readonly catsService: CatsService, ) { this.findOne = this.findOne.bind(this); } @Get(':catId') findOne() { console.log('catsService', this.catsService); return this.catsService.findOne('1'); } }
测试代码中的overrideProvider逻辑是正确的,修复控制器的this绑定问题后,依赖注入即可正常工作,测试也能顺利执行。
内容的提问来源于stack exchange,提问作者user3666653
相关产品推荐
相关产品推荐

