NestJS测试服务时使用Test.createTestingModule依赖注入失败问题
问题分析与解决:Nest测试中无法解析AdjustmentRepository依赖
问题描述
在为AdjustmentService编写测试套件时,运行测试返回以下错误:
Nest can't resolve dependencies of the AdjustmentService (?, RetailAdjustmentService, AdjustmentFileService). Please make sure that the argument AdjustmentRepository at index [0] is available in the RootTestModule context.
应用运行正常,但测试时依赖注入失败。相关代码如下:
服务构造函数
export class AdjustmentService { constructor( private readonly adjustmentsRepository: AdjustmentRepository, private readonly _retailAdjustmentService: RetailAdjustmentService, private readonly adjustmentFilesService: AdjustmentFileService ) {} //service functions here... }
测试代码
import { AdjustmentFileService } from "@/services/adjustmentFile.service"; import { Test, TestingModule } from "@nestjs/testing"; import { AdjustmentService } from "./adjustment.service"; import { Repository } from "typeorm"; import { AdjustmentEntity } from "@/entities/adjustment.entity"; import { getRepositoryToken } from "@nestjs/typeorm"; import { RetailAdjustmentService } from "@/services/retail/retailAdjustment.service"; describe("Adjustment Service", () => { let adjustmentService: AdjustmentService; let adjustementRepository: Repository<AdjustmentEntity>; beforeEach(async () => { const module = await Test.createTestingModule({ providers: [ AdjustmentService, AdjustmentFileService, RetailAdjustmentService, { provide: getRepositoryToken(AdjustmentEntity), useValue: { save: jest.fn(), createQueryBuilder: jest.fn(), delete: jest.fn(), where: jest.fn(), execute: jest.fn(), }, }, ], }).compile(); adjustmentService = module.get<AdjustmentService>(AdjustmentService); adjustementRepository = module.get<Repository<AdjustmentEntity>>( getRepositoryToken(AdjustmentEntity) ); }); describe("updateAdjustment", () => { it("should update the adjustment", async () => { const repoSpy = jest .spyOn(adjustementRepository, "save") .mockResolvedValue({ id: 1 } as AdjustmentEntity); const adjToUpdate = new AdjustmentEntity(); adjToUpdate.id = 1; adjToUpdate.pilars = "RT"; adjToUpdate.amount = 15000; expect( adjustmentService.updateAdjustment(1, adjToUpdate) ).resolves.toEqual({ id: 1 }); expect(repoSpy).toBeCalledWith(adjToUpdate); }); }); it("should return a list of adjustments", async () => {}); });
原因分析
问题核心是依赖注入的token不匹配:
AdjustmentService构造函数中注入的是自定义的AdjustmentRepository类- 测试代码中却提供了
AdjustmentEntity对应的默认Repository的token(getRepositoryToken(AdjustmentEntity))
Nest无法将这两个token关联,因此找不到AdjustmentRepository的实例。
解决方案
需要在测试模块中提供AdjustmentRepository对应的mock实现,使用其专属的token:
修改后的测试代码
import { AdjustmentFileService } from "@/services/adjustmentFile.service"; import { Test, TestingModule } from "@nestjs/testing"; import { AdjustmentService } from "./adjustment.service"; import { AdjustmentRepository } from "@/repositories/adjustment.repository"; // 导入自定义Repository import { RetailAdjustmentService } from "@/services/retail/retailAdjustment.service"; describe("Adjustment Service", () => { let adjustmentService: AdjustmentService; let adjustementRepository: AdjustmentRepository; beforeEach(async () => { const module = await Test.createTestingModule({ providers: [ AdjustmentService, AdjustmentFileService, RetailAdjustmentService, { // 使用自定义Repository作为token provide: AdjustmentRepository, useValue: { save: jest.fn(), createQueryBuilder: jest.fn(), delete: jest.fn(), where: jest.fn(), execute: jest.fn(), // 按需添加AdjustmentRepository中用到的其他方法 }, }, ], }).compile(); adjustmentService = module.get<AdjustmentService>(AdjustmentService); adjustementRepository = module.get<AdjustmentRepository>(AdjustmentRepository); }); describe("updateAdjustment", () => { it("should update the adjustment", async () => { const repoSpy = jest .spyOn(adjustementRepository, "save") .mockResolvedValue({ id: 1 } as any); const adjToUpdate = { id: 1, pilars: "RT", amount: 15000 }; await expect(adjustmentService.updateAdjustment(1, adjToUpdate)).resolves.toEqual({ id: 1 }); expect(repoSpy).toBeCalledWith(adjToUpdate); }); }); it("should return a list of adjustments", async () => {}); });
关键修改点
- 导入自定义
AdjustmentRepository:确保测试文件能引用到该类 - 替换provide的token:把
getRepositoryToken(AdjustmentEntity)改为AdjustmentRepository,自定义Repository本身就是可注入的provider - 调整类型声明:将
Repository<AdjustmentEntity>改为AdjustmentRepository,保持类型一致 - 完善mock方法:确保mock对象包含
AdjustmentRepository中被调用的所有方法
若你的AdjustmentRepository是通过@EntityRepository(TypeORM旧版)或@Repository(Nest+TypeORM新版)装饰的,也可使用getRepositoryToken(AdjustmentRepository)获取token,效果与直接使用类名一致。
内容的提问来源于stack exchange,提问作者Louguiman
相关产品推荐
相关产品推荐

