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

Nest.js无法创建多服务TestingModule,依赖注入报错求助

NestJS测试WeatherService依赖注入错误解决方案

问题背景

构建WeatherService测试模块时出现依赖注入错误,WeatherRepo依赖的WeatherRepository无法被解析。此前HttpModule遇到类似问题时,通过直接提供HttpService而非导入模块解决。不想使用自动模拟或覆盖方式,希望通过spyOn控制服务行为,但TestingModule配置失败。

错误信息

Error: Nest can't resolve dependencies of the WeatherRepo (?). Please make sure that the argument WeatherRepository at index [0] is available in the RootTestModule context.

Potential solutions:
- Is RootTestModule a valid NestJS module?
- If WeatherRepository is a provider, is it part of the current RootTestModule?
- If WeatherRepository is exported from a separate @Module, is that module imported within RootTestModule?
  @Module({
    imports: [ /* the Module containing WeatherRepository */ ]
  })

相关代码

weather.module.ts

@Module({
  imports: [HttpModule, SequelizeModule.forFeature([Weather])],
  controllers: [WeatherController],
  providers: [WeatherService, WeatherRepo],
  exports: [WeatherService],
})
export class WeatherModule {}

weather.service.spec.ts

describe('WeatherService', () => {
  beforeEach(async () => {
    const weatherServiceModule: TestingModule = await Test.createTestingModule({
      providers: [WeatherService, ConfigService, WeatherRepo],
      imports: [HttpModule],
    })
      // .overrideProvider(WeatherRepo)
      // .useValue(mockWeatherRepo)
      .compile();

    weatherService = weatherServiceModule.get<WeatherService>(WeatherService);
    weatherRepo = weatherServiceModule.get<WeatherRepo>(WeatherRepo);
    httpService = weatherServiceModule.get<HttpService>(HttpService);
  });

  it('should be defined', async () => {
    jest
      .spyOn(weatherRepo, 'findOrCreate')
      .mockResolvedValue(CreatedWeather(false));
    jest.spyOn(weatherRepo, 'update').mockResolvedValue(2);
    jest.spyOn(httpService, 'get').mockResolvedValue({ data: CreateWeather() });
  });
});

weather.service.ts

@Injectable()
export class WeatherService {
  constructor(
    private readonly httpService: HttpService,
    private readonly config: ConfigService,
    private readonly weatherRepository: WeatherRepo,
  ) {}
}

weather.repo.ts

@Injectable()
export class WeatherRepo {
  constructor(@InjectModel(Weather) private weatherModel: typeof Weather) {}
}

解决方案

问题核心是测试模块未提供WeatherRepo所需的Weather模型依赖。WeatherRepo通过@InjectModel(Weather)注入模型,该模型由SequelizeModule.forFeature([Weather])提供,因此需在测试模块中补充该依赖,或手动模拟模型。

方案1:导入Sequelize测试模块

在测试模块中导入SequelizeModule.forFeature([Weather]),同时配置测试用Sequelize(比如内存数据库):

beforeEach(async () => {
  const weatherServiceModule: TestingModule = await Test.createTestingModule({
    providers: [WeatherService, ConfigService, WeatherRepo],
    imports: [
      HttpModule,
      SequelizeModule.forFeature([Weather]),
      SequelizeModule.forRoot({
        dialect: 'sqlite',
        storage: ':memory:',
        autoLoadModels: true,
        synchronize: true,
      })
    ],
  }).compile();

  weatherService = weatherServiceModule.get<WeatherService>(WeatherService);
  weatherRepo = weatherServiceModule.get<WeatherRepo>(WeatherRepo);
  httpService = weatherServiceModule.get<HttpService>(HttpService);
});

方案2:手动模拟Weather模型

如果不想连接数据库,直接模拟Weather模型并注入测试模块:

const mockWeatherModel = {
  findOrCreate: jest.fn(),
  update: jest.fn(),
  // 按需添加其他模型方法
};

beforeEach(async () => {
  const weatherServiceModule: TestingModule = await Test.createTestingModule({
    providers: [
      WeatherService,
      ConfigService,
      WeatherRepo,
      {
        provide: getModelToken(Weather),
        useValue: mockWeatherModel,
      },
    ],
    imports: [HttpModule],
  }).compile();

  weatherService = weatherServiceModule.get<WeatherService>(WeatherService);
  weatherRepo = weatherServiceModule.get<WeatherRepo>(WeatherRepo);
  httpService = weatherServiceModule.get<HttpService>(HttpService);
});

方案3:用spyOn控制WeatherRepo行为(符合需求)

先通过上述任一方案解决依赖问题,再在测试用例中用spyOn控制方法行为:

it('should process weather data correctly', async () => {
  // 模拟WeatherRepo方法
  jest.spyOn(weatherRepo, 'findOrCreate').mockResolvedValue([mockWeatherInstance, false]);
  // 模拟HttpService方法
  jest.spyOn(httpService, 'get').mockResolvedValue({ data: mockApiResponse });

  // 执行测试逻辑
  const result = await weatherService.fetchAndSaveWeather();
  
  // 断言验证
  expect(weatherRepo.findOrCreate).toHaveBeenCalledWith(expect.any(Object));
  expect(httpService.get).toHaveBeenCalledWith(expect.any(String));
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.07 04:52:45