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

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 () => {});
});

关键修改点

  1. 导入自定义AdjustmentRepository:确保测试文件能引用到该类
  2. 替换provide的token:把getRepositoryToken(AdjustmentEntity)改为AdjustmentRepository,自定义Repository本身就是可注入的provider
  3. 调整类型声明:将Repository<AdjustmentEntity>改为AdjustmentRepository,保持类型一致
  4. 完善mock方法:确保mock对象包含AdjustmentRepository中被调用的所有方法

若你的AdjustmentRepository是通过@EntityRepository(TypeORM旧版)或@Repository(Nest+TypeORM新版)装饰的,也可使用getRepositoryToken(AdjustmentRepository)获取token,效果与直接使用类名一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 04:37:53