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

如何在ES模块模式下使用Jest对命名导入的方法进行Mock/Spy?

如何在ES模块模式下使用Jest对命名导入的方法进行Mock/Spy?

这个问题绝对是ES模块模式下Jest Mocking的经典坑!当你用import { statSync } from 'node:fs'这种命名导入方式时,原来针对模块对象的spyOn就失效了——原因很简单:命名导入会把函数的直接引用绑定到当前模块作用域,而不是每次调用都去原模块对象上取方法。所以你之前替换fs.statSync的操作,根本影响不到my-func.js里已经导入的那个独立的statSync函数,自然就会出现stats为undefined的报错。

别慌,咱们有两种靠谱的解决方案:

方案一:用jest.mock直接模拟命名导出

这种方式适合大多数场景,既能精准mock目标函数,还能保留原模块的其他方法(如果需要的话)。修改你的测试代码如下:

// my-func.test.js
import { jest } from '@jest/globals';
import { myFunc } from './my-func.js';
import { statSync } from 'node:fs';

// 模拟node:fs的命名导出
jest.mock('node:fs', () => ({
  // 保留原模块的其他所有方法(避免影响其他依赖fs的逻辑)
  ...jest.requireActual('node:fs'),
  // 替换statSync为我们的mock函数
  statSync: jest.fn().mockReturnValue({ isDirectory: () => true })
}));

it('should work', () => {
  expect(myFunc('/test')).toBeTruthy();
  // 验证mock函数被正确调用
  expect(statSync).toHaveBeenCalledWith('/test', { throwIfNoEntry: false });
});

如果你的测试完全不需要fs的其他方法,也可以简化mock逻辑,直接返回包含statSync的对象就行。

方案二:用jest.unstable_mockModule(ES模块专属方式)

Jest为ES模块专门提供了unstable_mockModuleAPI(虽然名字带unstable,但在Jest 29版本已经很实用了),这种方式更贴合ES模块的加载机制。注意要先mock模块,再导入目标文件:

// my-func.test.js
import { jest } from '@jest/globals';

// 先mock fs模块
await jest.unstable_mockModule('node:fs', () => ({
  statSync: jest.fn().mockReturnValue({ isDirectory: () => true })
}));

// 等待mock完成后,再导入被测试模块和fs方法
const { myFunc } = await import('./my-func.js');
const { statSync } = await import('node:fs');

it('should work', () => {
  expect(myFunc('/test')).toBeTruthy();
  expect(statSync).toHaveBeenCalled();
});

这里要注意顺序:必须先完成模块mock,再导入被测试的myFunc,否则导入的还是原函数。另外,Jest支持顶级await,所以直接写在测试文件顶部就行。

再啰嗦两句为什么原来的方法不行

当你用import fs from 'node:fs'时,你调用的是fs.statSync——每次调用都会去fs这个对象上查找方法,所以spyOn能替换掉这个对象属性,从而生效。但命名导入statSync时,相当于把函数直接“复制”到了my-func.js的作用域里,和原fs对象彻底解绑了,spyOn自然就碰不到它了。

备注:内容来源于stack exchange,提问作者Marty ZHANG

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.14 12:52:59