使用Jest进行NestJS E2E测试时依赖服务未定义无有效错误
问题原因分析
出现这个问题的核心原因有两种可能:
- 控制器实例的依赖注入未正确完成:手动实例化控制器时虽然传了服务,但E2E测试场景下未通过Nest的DI容器管理实例,或者服务本身还有嵌套依赖未正确初始化;
- 方法调用时
this指向丢失:调用控制器方法时,未通过控制器实例直接调用,导致方法内的this指向undefined。
解决方案
方案1:改用Nest官方推荐的E2E测试方式(最稳妥)
E2E测试应该模拟真实请求,通过supertest调用API接口,同时用Test.createTestingModule构建完整的测试模块,让Nest自动处理依赖注入:
import { Test } from '@nestjs/testing'; import { INestApplication } from '@nestjs/common'; import * as request from 'supertest'; import { MyController } from './my.controller'; import { AService } from './a.service'; import { BService } from './b.service'; describe('MyController (E2E)', () => { let app: INestApplication; beforeEach(async () => { const moduleFixture = await Test.createTestingModule({ controllers: [MyController], providers: [AService, BService], // 如果服务有其他依赖,也要一并加入,或者直接导入对应模块 }).compile(); app = moduleFixture.createNestApplication(); await app.init(); }); afterEach(async () => { await app.close(); }); it('/login (POST)', async () => { const loginDto = { /* 你的测试数据 */ }; return request(app.getHttpServer()) .post('/login') .send(loginDto) .expect(200) // 根据你的接口预期调整状态码 .expect((res) => { // 这里可以添加响应体的断言 }); }); });
这种方式完全模拟真实请求流程,不会出现this指向或依赖注入的问题,也更符合E2E测试的初衷。
方案2:修复直接调用控制器方法的测试(如果坚持这种方式)
如果一定要直接调用控制器方法,需要注意两点:
- 通过Nest的DI容器获取控制器实例,而非手动
new:
import { Test } from '@nestjs/testing'; import { MyController } from './my.controller'; import { AService } from './a.service'; import { BService } from './b.service'; describe('MyController', () => { let controller: MyController; beforeEach(async () => { const moduleRef = await Test.createTestingModule({ controllers: [MyController], providers: [AService, BService], }).compile(); controller = moduleRef.get<MyController>(MyController); }); it('should be defined', () => { expect(controller).toBeDefined(); }); it('should login successfully', async () => { const loginDto = { /* 测试数据 */ }; // 必须通过控制器实例直接调用方法,确保this指向正确 const result = await controller.login(loginDto); // 添加断言 expect(result).toBeDefined(); }); });
- 禁止单独提取方法调用:比如不要写
const login = controller.login; await login(dto);,这种写法会丢失this指向,导致this.aService为undefined。
额外排查点
如果服务本身有嵌套依赖(比如AService依赖其他Repository或服务),测试模块中必须把所有依赖都声明或mock,否则Nest无法完成DI,控制器内的服务会是undefined。
内容的提问来源于stack exchange,提问作者Raddaya
相关产品推荐
相关产品推荐

