Jest Mock NPM包heartbeats方法时报mockImplementation未定义如何解决
问题核心原因
你没有对heartbeats这个NPM包做Mock,直接导入了原始包,原始包不存在Heartbeats.heart这个属性,自然Heartbeats.heart.createEvent就是undefined,调用mockImplementation就会抛出你遇到的错误。
而且你调用checkUp时会直接把mockHeart作为参数传入,完全不需要依赖原始heartbeats包的结构来构造Mock对象,直接手动构造符合入参要求的Mock对象即可。
修复代码
你只需要把测试用例里构造mockHeart和mockCreateEvent的部分替换为以下代码即可:
it('should auto kill app after checks', async () => { const mockApp = new MockApp() as unknown as jest.Mocked<App>; // 直接手动构造mockHeart对象,不需要依赖原始heartbeats包 const mockCreateEvent = jest.fn(); const mockHeart = { createEvent: mockCreateEvent }; // 这里就可以正常调用mockImplementation了 mockCreateEvent.mockImplementation((beats, iter, cb) => { cb(null, null); }); mockSecondCheckStatus.mockResolvedValueOnce(false); mockApp.requestSingleInstanceLock.mockReturnValue(true); // 注意:checkUp返回类型是Promise<void>,没有返回值,你这里拿到的isRunning是undefined,后续expect(isRunning).toBe(false)会失败,需要对应调整逻辑 await checkUp(mockApp, mockHeart, 1, 1); await main(mockApp); expect(mockApp.quit).toHaveBeenCalledTimes(1); // 下面这行需要你根据实际业务逻辑调整,因为checkUp本身没有返回值 // expect(isRunning).toBe(false); });
其他补充说明
- 如果你的业务逻辑中需要用到
createEvent回调的count、last参数,只需要在调用cb的时候传入对应的值即可,比如cb(1, true)。 - 如果你其他测试用例需要用到
heartbeats的其他方法,可以统一使用jest.mock('heartbeats')对整个包做Mock,再按需指定导出的方法实现。
内容的提问来源于stack exchange,提问作者Datenshi
相关产品推荐
相关产品推荐

