You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Jest模拟ES模块jszip方法报错,如何正确Mock并监听?

正确Mock JSZip并监听方法的解决方案

你的测试报错是因为JSZip的Mock结构写错了,同时忽略了folder方法返回的子文件夹对象也需要包含file方法的细节。以下是修正后的完整方案:

错误根源

  1. 原jest.mock的模块导出结构错误:JSZip是默认导出的类,你之前的写法把模拟类嵌套在了返回对象的default属性里,导致new Jszip()实例化的是外层的mock函数,而非你定义的模拟类。
  2. 未处理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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 15:35:28