You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Jest进行NestJS E2E测试时依赖服务未定义无有效错误

问题原因分析

出现这个问题的核心原因有两种可能:

  1. 控制器实例的依赖注入未正确完成:手动实例化控制器时虽然传了服务,但E2E测试场景下未通过Nest的DI容器管理实例,或者服务本身还有嵌套依赖未正确初始化;
  2. 方法调用时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:修复直接调用控制器方法的测试(如果坚持这种方式)

如果一定要直接调用控制器方法,需要注意两点:

  1. 通过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();
  });
});
  1. 禁止单独提取方法调用:比如不要写const login = controller.login; await login(dto);,这种写法会丢失this指向,导致this.aService为undefined。

额外排查点

如果服务本身有嵌套依赖(比如AService依赖其他Repository或服务),测试模块中必须把所有依赖都声明或mock,否则Nest无法完成DI,控制器内的服务会是undefined。

内容的提问来源于stack exchange,提问作者Raddaya

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 04:33:19