如何使用Jest正确Mock ES6类?工厂参数配置jest.mock报方法不存在
问题核心原因
你的错误写法踩了两个Jest Mock的典型规则误区:
jest.mock()是纯副作用方法,没有任何返回值。它的作用是告诉Jest“测试运行时,遇到引入目标模块的地方,就用后面工厂返回的内容替换真实模块”,方法本身执行完返回undefined。你写的const projectSettings = jest.mock(...)拿到的永远是undefined,根本不是你在工厂函数里定义的构造函数,把undefined传进测试用例,自然调用getProjectDir会抛出方法不存在的错误。- 没有完成类的实例化逻辑:就算正确拿到了mock的构造函数,你也没有在测试用例里通过
new生成实例,直接把构造函数本身传给被测方法,调用实例方法时也会触发报错。
符合规则的正确实现方式
1. 编写模块mock逻辑
在测试文件顶部写mock定义,注意不要接收jest.mock的返回值:
// 会被Jest自动提升到文件最顶部最先执行,替换./projectSettings的真实实现 jest.mock('./projectSettings', () => { // 提前构造带jest.fn()的实例对象 const mockInstance = { getProjectDir: jest.fn(), setProjectDir: jest.fn() }; // 返回mock类:调用new时直接返回上面定义的mock实例 return jest.fn().mockImplementation(() => mockInstance); });
2. 引入被mock的模块并实例化
正常import被mock的模块,手动实例化后拿到带mock方法的对象:
import ProjectSettings from './projectSettings'; // 实例化mock类,拿到的就是提前定义的带jest.fn()的对象 const projectSettings = new ProjectSettings();
3. 调整测试用例逻辑
把实例化好的mock对象传入被测方法,必要时给mock方法预设返回值,适配业务逻辑调用:
test('Set Project Directory Menu click should open dialog', async () => { // 给getProjectDir设置默认返回值,匹配业务里的调用逻辑 projectSettings.getProjectDir.mockReturnValue('/default/test/path'); const setDirMenuItem = subMenu.getSetProjectDirSubMenu( <any>mainWindow, <any>projectSettings ); await setDirMenuItem.click(); expect(dialog.showOpenDialog).toHaveBeenCalledTimes(1); });
简化提示:如果
./projectSettings是直接导出对象而非ES6类,可以去掉构造函数包裹,简化mock写法,不需要手动实例化:jest.mock('./projectSettings', () => ({ getProjectDir: jest.fn(), setProjectDir: jest.fn() }));这种写法下import拿到的直接就是带mock方法的对象,可以直接传入被测逻辑使用。
内容的提问来源于stack exchange,提问作者IamaC
相关产品推荐
相关产品推荐

