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

