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

NestJS Jest单元测试中AppLogger依赖注入失败问题排查

NestJS构造函数注入AppLogger依赖失败排查方案

问题现象

  • HealthCheckController构造函数中,HealthCheckService实例注入成功,但AppLogger始终为null
  • 注释控制器里的appLogger参数后,控制器能正常初始化,但执行await module.resolve<AppLogger>(AppLogger)会直接失败

相关代码片段

控制器代码

export class HealthCheckController {
  constructor(@Inject('HealthCheckService') private healthCheckService: HealthCheckService, private appLogger: AppLogger) {
  }
}

测试代码

beforeEach(async () => {
    module = await Test.createTestingModule({
      controllers: [HealthCheckController],
      providers: [
        AppLoggerNope.getProvider(),
       { provide: 'HealthCheckService', useClass: HealthCheckService },
      ],
    })
      .compile();
    controller = await module.resolve<HealthCheckController>(HealthCheckController);
    const logger = await module.resolve<AppLogger>(AppLogger);
    service = await module.resolve<HealthCheckService>('HealthCheckService');
  });

AppLoggerNope代码

export class AppLoggerNope {
  static getProvider() {
    return {
      provide: AppLogger,
      useValue: {}
    }
  }
}

问题根源

  1. AppLogger类未标记为可注入:NestJS的DI容器要求所有需要注入的类必须添加@Injectable()装饰器,否则容器无法识别这个类型作为注入令牌。即使使用自定义提供者(useValue),如果AppLogger本身没有被标记,容器无法关联对应的实例。
  2. 测试容器无法匹配令牌:调用module.resolve<AppLogger>(AppLogger)时,容器找不到对应令牌的提供者,说明AppLogger这个类型没有被正确注册到测试模块的DI系统中。

解决步骤

1. 给AppLogger添加@Injectable()装饰器

import { Injectable } from '@nestjs/common';

@Injectable()
export class AppLogger {
  // 实现日志方法,比如log、error等
}

2. 验证自定义提供者的正确性

确保AppLoggerNope.getProvider()返回的提供者中,provide字段的令牌与控制器中注入的AppLogger类完全一致。只要AppLogger被标记为@Injectable(),当前的provide: AppLogger配置就是有效的。

3. 调整测试代码中的实例获取方式

建议用module.get()替代module.resolve(),前者更适合测试场景下从容器获取实例:

beforeEach(async () => {
    module = await Test.createTestingModule({
      controllers: [HealthCheckController],
      providers: [
        AppLoggerNope.getProvider(),
        { provide: 'HealthCheckService', useClass: HealthCheckService },
      ],
    }).compile();

    controller = module.get<HealthCheckController>(HealthCheckController);
    const logger = module.get<AppLogger>(AppLogger);
    service = module.get<HealthCheckService>('HealthCheckService');
  });

4. 确认控制器注入语法

如果AppLogger是类类型注入,不需要额外添加@Inject()装饰器,只要类本身是@Injectable()且已在模块中注册,就能正常注入:

constructor(
  @Inject('HealthCheckService') private healthCheckService: HealthCheckService, 
  private appLogger: AppLogger // 直接使用类类型注入即可
) {}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 03:50:14