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

如何通过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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 05:30:43