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

如何正确模拟构造函数含字符串参数的Injectable服务?

如何正确模拟带有自定义注入令牌的NestJS服务?

我有一个简单的可注入服务,代码如下:

@Injectable()
export class MyService {
  constructor(@Inject('Container') container: string) {
    // ...
  }
}

我尝试对其进行模拟,测试模块代码如下:

const module = await Test.createTestingModule({
  imports: [
    ConfigModule.forRoot({
      isGlobal: true,
    }),
  ],
  providers: [
    {
      provide: MyService,
      useValue: {
        find: (id: string) => 'test'
      }
    },
    {
      provide: 'Container',
      useValue: 'AnyValue'
    },
  ],
}).compile();
await module.init();

但模拟并未生效,该服务仍在发起网络请求。请问该如何正确模拟这个服务?


可能的原因及解决方法

1. 确保使用测试容器中的模拟实例

检查测试代码是否从测试模块中获取MyService实例,而非直接创建真实服务:

// 正确方式:从测试容器获取模拟实例
const myService = module.get<MyService>(MyService);
// 测试中使用这个实例调用方法

如果直接通过new MyService(...)创建实例,测试模块的模拟配置完全不会生效,自然会执行真实服务的网络请求逻辑。

2. 显式覆盖提供者避免依赖冲突

如果测试模块导入的其他模块(比如全局ConfigModule)间接引入了真实的MyService,NestJS可能会优先加载真实实例。此时使用overrideProvider强制替换:

const module = await Test.createTestingModule({
  imports: [ConfigModule.forRoot({ isGlobal: true })],
})
.overrideProvider(MyService)
.useValue({
  find: (id: string) => 'test',
  // 补充所有需要模拟的方法,比如发起请求的方法
  fetchData: () => Promise.resolve('mock response')
})
.compile();

3. 完整模拟服务的所有用到的方法

如果MyService中有多个方法,而你只模拟了find,未被模拟的方法(比如发起网络请求的方法)会执行真实逻辑。需要确保模拟对象覆盖测试中用到的所有方法:

{
  provide: MyService,
  useValue: {
    find: (id: string) => 'test',
    // 例如:模拟发起网络请求的方法
    sendRequest: () => Promise.resolve({ data: 'mock' })
  }
}

4. 控制全局模块的影响

全局ConfigModule可能引入未预期的依赖,导致真实服务被加载。可以尝试关闭全局配置,或者限制模块的作用范围:

ConfigModule.forRoot({
  isGlobal: false, // 关闭全局模式
  // 测试所需的配置项
})

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.22 09:15:11