使用Jest部分Mock AdmZip时getEntries()原方法报错如何解决
Jest Mock adm-zip 保留原生实例方法问题
问题背景
尝试了所有公开的相关示例写法均无法正常运行,其中最接近预期思路的写法实际执行依旧存在问题。
实现目标
保留AdmZip所有原生方法的原有逻辑,仅对writeZip和updateFile两个方法进行Mock,后续可通过Spy对这两个方法的调用情况做断言校验。
现存报错
运行代码时抛出admZip.getEntries() is not a function错误,初步判断是Mock逻辑中引入实际模块的写法有误,需要找到正确的Mock写法,保留getEntries等所有AdmZip原生实例方法。
已尝试的失败写法
- 第一种写法:
jest.mock('adm-zip', () => { const actual = jest.requireActual('adm-zip'); return function(): AdmZip { return { ...actual, // 原本期望通过展开操作符引入getEntries()等原生方法 writeZip: jest.fn(), updateFile: jest.fn() } } });
- 第二种写法:
jest.mock('adm-zip', () => { const actual = jest.requireActual('adm-zip'); return jest.fn().mockImplementation(() => ({ ...actual, writeZip: jest.fn(), updateFile: jest.fn() })) });
- 第三种写法:
jest.mock('adm-zip', () => { const actual = jest.requireActual('adm-zip'); return { __esModule: true, ...actual, AdmZip: jest.fn().mockImplementation(() => { return { ...jest.requireActual('adm-zip'), writeZip: jest.fn(), updateFile: jest.fn() } }) } });
错误原因
三种写法的核心问题:
jest.requireActual('adm-zip')获取到的是模块导出的AdmZip构造函数,而非构造函数的原型对象。getEntries等实例方法都挂载在构造函数的prototype上,直接展开构造函数本身根本拿不到这些实例方法,最终生成的Mock对象自然缺少对应方法,调用时就会抛出is not a function的错误。
正确实现方案
核心思路是先创建真实的AdmZip实例(自带所有原生原型方法),再在这个真实实例上覆盖需要Mock的两个方法即可,不需要手动搬运原型方法。
CommonJS 导入场景(const AdmZip = require('adm-zip'))
jest.mock('adm-zip', () => { const actualAdmZip = jest.requireActual('adm-zip'); // 兼容不同版本的导出差异 const AdmZipConstructor = actualAdmZip.default || actualAdmZip; return jest.fn().mockImplementation((...constructorArgs) => { // 生成真实实例,自带所有原生方法 const realInstance = new AdmZipConstructor(...constructorArgs); // 仅覆盖需要Mock的两个方法 realInstance.writeZip = jest.fn(); realInstance.updateFile = jest.fn(); return realInstance; }) });
ES Module 导入场景(import AdmZip from 'adm-zip' / import { AdmZip } from 'adm-zip')
jest.mock('adm-zip', () => { const actualAdmZip = jest.requireActual('adm-zip'); const AdmZipConstructor = actualAdmZip.default || actualAdmZip; const mockFactory = jest.fn().mockImplementation((...constructorArgs) => { const realInstance = new AdmZipConstructor(...constructorArgs); realInstance.writeZip = jest.fn(); realInstance.updateFile = jest.fn(); return realInstance; }); return { __esModule: true, ...actualAdmZip, default: mockFactory, AdmZip: mockFactory } });
内容的提问来源于stack exchange,提问作者MushyPeas
相关产品推荐
相关产品推荐

