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
相关产品推荐
相关产品推荐

