如何通过Jest正确Mock Xlsx(SheetJS)的read函数?
解决Jest无法Mock SheetJS(xlsx)库read函数的问题
问题场景
业务代码使用SheetJS(xlsx)的read函数处理文件,单元测试中尝试用Jest Mock替换该函数,但实际执行了原函数并抛出错误,已尝试添加__esModule: true和moduleNameMapper映射但未解决问题。
业务代码
import { read } from 'xlsx'; export default function foo(file){ return read(file); };
单元测试代码(原错误版本)
import foo from '../../../src/components/upload/demo'; it('foo', () => { const mockedXlsx = { read: () => 'mocked_result' }; jest.mock('xlsx', () => mockedXlsx); const mockedFile = { arrayBuffer: () => {} }; spyOn(mockedFile, 'arrayBuffer'); const result = foo(mockedFile); expect(result).toBe('mocked_result'); expect(mockedFile.arrayBuffer).toHaveBeenCalled(); });
依赖配置(package.json)
"xlsx": "https://cdn.sheetjs.com/xlsx-0.19.0/xlsx-0.19.0.tgz"
报错信息
TypeError: e.slice is not a function
解决方案
1. 调整Mock位置与模块结构
Jest的jest.mock会被自动提升到模块作用域顶部,因此不能放在it测试块内部。同时需要正确模拟ES模块的导出结构:
修改后的测试代码:
import foo from '../../../src/components/upload/demo'; // 将jest.mock移至模块顶部 jest.mock('xlsx', () => ({ __esModule: true, // 标记为ES模块,匹配业务代码的导入语法 read: jest.fn(() => 'mocked_result') })); // 导入Mock后的read函数,用于调用断言 import { read } from 'xlsx'; it('foo', () => { const mockedFile = { arrayBuffer: jest.fn() }; const result = foo(mockedFile); expect(result).toBe('mocked_result'); expect(read).toHaveBeenCalledWith(mockedFile); expect(mockedFile.arrayBuffer).toHaveBeenCalled(); });
2. 检查Jest转换配置
若上述调整后仍不生效,需确保Jest不会忽略xlsx模块的转换,修改jest.config.js:
module.exports = { // 其他配置... transformIgnorePatterns: [ '/node_modules/(?!xlsx/)' // 允许Jest转换xlsx模块 ] };
关键说明
jest.mock必须放在模块顶层,否则Jest的提升机制会导致Mock失效- 添加
__esModule: true是模拟ES模块导出的必要配置,匹配业务代码中的命名导入语法 - 使用
jest.fn()创建Mock函数,可更便捷地进行调用断言
内容的提问来源于stack exchange,提问作者Stefan
相关产品推荐
相关产品推荐

