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

NestJS Jest单测试文件Mock两个服务时第二个服务方法调用报错

你遇到的报错:

TypeError: this.orderService.payAllWithIds is not a function

以及打印orderService得到TableService mock内容的问题,核心原因是NestJS测试依赖注入容器加载了错误的服务实例,两个服务的mock出现了token匹配冲突,导致OrderService对应的实例实际是TableService的mock。

解决方案

按以下步骤排查修改即可解决:

方案1:直接在测试模块内声明mock(推荐,避免全局mock冲突)

删掉原有的jest.mock语句和单独的__mocks__/order.service.ts文件,直接在TestingModule的providers中显式声明mock值,完全控制每个服务的返回内容:

// overview.controller.spec.ts
import { OrderService } from './orders/order.service';
import { TableService } from './tables/table.service';
import { tableWithOpenOrder } from 'test/stubs';

// 删掉原来的两个jest.mock语句

describe('OverviewController', () => {
  let controller: OverviewController;
  let orderService: OrderService;
  let tableService: TableService;

  beforeEach(async () => {
    const module: TestingModule = await Test.createTestingModule({
      controllers: [OverviewController],
      providers: [
        // 显式声明OrderService的mock
        {
          provide: OrderService,
          useValue: {
            payAllWithIds: jest.fn().mockResolvedValue([tableWithOpenOrder()]),
            // 测试中用到的其他OrderService方法可以在这里补充
          }
        },
        { provide: getModelToken('order'), useValue: OrderSchema },
        // 显式声明TableService的mock
        {
          provide: TableService,
          useValue: {
            removePaymentRequest: jest.fn().mockResolvedValue(/* 填入你需要的返回值 */),
            // 测试中用到的其他TableService方法可以在这里补充
          }
        },
        { provide: getModelToken('table'), useValue: TableSchema },
      ],
    }).compile();

    controller = module.get<OverviewController>(OverviewController);
    orderService = module.get<OrderService>(OrderService);
    tableService = module.get<TableService>(TableService);
  });

  // 后面的测试代码保持不变即可
  describe('payTable', () => {
    describe('when payTable is called', () => {
      beforeEach(async () => {
        await controller.payTable(tableStub()._id);
      });

      it('then the service is called', () => {
        expect(tableService.removePaymentRequest).toBeCalledWith(tableStub()._id);
        expect(orderService.payAllWithIds).toBeCalled();
      });
    })
  })
})

方案2:保留全局__mocks__文件的修正方法

如果你要继续使用单独的mock文件,需要检查两项配置:

  • 确认mock文件路径完全匹配:./orders/order.service对应的mock必须放在./orders/__mocks__/order.service.ts,./tables/table.service对应的mock必须放在./tables/__mocks__/table.service.ts,不要把两个mock都放在根目录的__mocks__文件夹下,路径不匹配会导致Jest加载错误的mock。
  • 在beforeEach中添加mock重置逻辑,避免单例复用导致的冲突:
beforeEach(() => {
  jest.clearAllMocks();
});

修改完成后重新运行测试,orderService就会返回正确的mock实例,payAllWithIds调用报错也会消失。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 20:45:00