如何在单函数中Mock多个方法?Jest测试报错排查
解决Jest Mock类时多次mockImplementation覆盖导致方法失效的问题
你遇到的问题核心在于:每次调用mockImplementation都会完全覆盖之前的mock实现,而不是为类追加方法。如果分开三次调用这个方法,只有最后一次的实现会被保留,前两个方法自然不存在,调用时就会抛出TypeError: xxx is not a function。
下面是几种可行的解决方式:
方式一:一次性为类的所有原型方法添加mock
先通过jest.mockmock整个类,再逐个给类的prototype属性赋值mock函数:
// DeliveryService.test.ts import DeliveryRepository from './DeliveryRepository'; import DeliveryService from './DeliveryService'; // 先mock整个仓库类 jest.mock('./DeliveryRepository'); // 类型断言,方便后续操作mock方法 const MockedDeliveryRepo = DeliveryRepository as jest.MockedClass<typeof DeliveryRepository>; // 为每个异步方法指定mock实现 MockedDeliveryRepo.prototype.function1 = jest.fn().mockResolvedValue('func1 mock result'); MockedDeliveryRepo.prototype.function2 = jest.fn().mockResolvedValue('func2 mock result'); MockedDeliveryRepo.prototype.function3 = jest.fn().mockResolvedValue('func3 mock result'); test('postDelivery 会依次调用仓库的三个方法', async () => { const service = new DeliveryService(); await service.postDelivery(); // 验证每个方法都被调用 expect(MockedDeliveryRepo.prototype.function1).toHaveBeenCalled(); expect(MockedDeliveryRepo.prototype.function2).toHaveBeenCalled(); expect(MockedDeliveryRepo.prototype.function3).toHaveBeenCalled(); });
方式二:使用jest.mock的工厂函数一次性定义所有mock方法
直接在jest.mock的回调里返回类的mock实现,一次性包含所有方法:
// DeliveryService.test.ts // 先mock仓库类,在工厂函数里定义所有实例方法的mock jest.mock('./DeliveryRepository', () => { return jest.fn().mockImplementation(() => ({ function1: jest.fn().mockResolvedValue('func1 mock result'), function2: jest.fn().mockResolvedValue('func2 mock result'), function3: jest.fn().mockResolvedValue('func3 mock result'), })); }); import DeliveryRepository from './DeliveryRepository'; import DeliveryService from './DeliveryService'; test('postDelivery 会依次调用仓库的三个方法', async () => { const service = new DeliveryService(); await service.postDelivery(); // 获取mock的仓库实例 const repoInstance = DeliveryRepository.mock.instances[0]; expect(repoInstance.function1).toHaveBeenCalled(); expect(repoInstance.function2).toHaveBeenCalled(); expect(repoInstance.function3).toHaveBeenCalled(); });
方式三:单测试用例中修改单个方法的mock实现
如果需要在不同测试用例中调整某个方法的返回值,不需要重新调用mockImplementation,直接修改对应方法的mock即可:
// 全局先mock好所有方法 const MockedDeliveryRepo = DeliveryRepository as jest.MockedClass<typeof DeliveryRepository>; MockedDeliveryRepo.prototype.function1 = jest.fn().mockResolvedValue('default result'); MockedDeliveryRepo.prototype.function2 = jest.fn().mockResolvedValue('default result'); MockedDeliveryRepo.prototype.function3 = jest.fn().mockResolvedValue('default result'); test('测试function1返回自定义结果', async () => { // 仅修改function1的mock实现,其他方法保持默认 MockedDeliveryRepo.prototype.function1.mockResolvedValue('custom result'); const service = new DeliveryService(); await service.postDelivery(); expect(MockedDeliveryRepo.prototype.function1).toHaveReturnedWith('custom result'); });
关键注意点
- 绝对不要多次调用
mockImplementation来为类添加多个方法,这会完全覆盖之前的mock内容 - 优先选择一次性定义所有mock方法的方式,避免覆盖问题
- 如果需要动态修改mock行为,直接针对单个方法的mock函数进行修改即可
内容的提问来源于stack exchange,提问作者The Blues
相关产品推荐
相关产品推荐

