Jest模拟ES模块jszip方法报错,如何正确Mock并监听?
正确Mock JSZip并监听方法的解决方案
你的测试报错是因为JSZip的Mock结构写错了,同时忽略了folder方法返回的子文件夹对象也需要包含file方法的细节。以下是修正后的完整方案:
错误根源
- 原
jest.mock的模块导出结构错误:JSZip是默认导出的类,你之前的写法把模拟类嵌套在了返回对象的default属性里,导致new Jszip()实例化的是外层的mock函数,而非你定义的模拟类。 - 未处理
folder方法的返回值:zip.folder('folder')会返回一个子文件夹对象,该对象同样拥有file方法,原mock中mockFolder没有返回对应结构,会导致可选链调用逻辑不符合预期。
修正后的测试代码
// app.test.ts import { runJszip } from './app'; // 模拟file方法,根Zip对象和子文件夹对象共用此方法 const mockFile = jest.fn(); // 模拟folder方法,返回包含file方法的子文件夹对象 const mockFolder = jest.fn(() => ({ file: mockFile })); // 模拟JSZip类,实例化后返回完整的方法结构 const MockJszip = jest.fn(() => ({ folder: mockFolder, file: mockFile, generateAsync: jest.fn().mockResolvedValue({}) // 模拟异步生成Blob的返回值 })); // 正确Mock JSZip模块:默认导出为模拟类 jest.mock('jszip', () => ({ __esModule: true, default: MockJszip })); test('JSZip方法调用符合预期', async () => { await runJszip(); // 验证folder方法调用次数和参数 expect(mockFolder).toHaveBeenCalledTimes(1); expect(mockFolder).toHaveBeenCalledWith('folder'); // 验证file方法被调用2次,参数正确 expect(mockFile).toHaveBeenCalledTimes(2); expect(mockFile).toHaveBeenNthCalledWith(1, 'file.txt', 'just some text'); expect(mockFile).toHaveBeenNthCalledWith(2, 'file.txt', 'just some text'); // 验证generateAsync方法被正确调用 expect(MockJszip.mock.instances[0].generateAsync).toHaveBeenCalledWith({ type: 'blob' }); });
关键修正点
- 模块Mock结构:直接在
jest.mock的工厂函数中导出__esModule: true和default: MockJszip,确保import Jszip from 'jszip'拿到的是模拟类。 - folder方法返回值:让
mockFolder返回包含file方法的对象,匹配JSZip的实际行为,保证zip.folder()?.file的调用能触发mock函数。 - generateAsync模拟:添加该方法的mock并返回resolved值,避免异步函数因未处理的Promise导致测试超时。
内容的提问来源于stack exchange,提问作者johannchopin
相关产品推荐
相关产品推荐

