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

能否在不修改原模块的前提下用Jest模拟JavaScript独立函数?

解决方案

可以实现,关键是利用Jest的模块模拟能力结合ES模块的绑定特性,在保留subtract原始实现的同时替换内部的add引用。

具体实现

修改math.test.js如下:

// 模拟整个math模块,同时保留真实的subtract实现
jest.mock('./math.js', () => {
  // 加载模块的真实代码
  const original = jest.requireActual('./math.js');
  return {
    ...original,
    // 将add替换为可模拟的jest函数
    add: jest.fn(),
  };
});

// 导入模拟后的模块
import * as math from './math.js';
import { subtract } from './math.js';

describe('math', () => {
  it('should return 1234', () => {
    // 设置add的模拟返回值
    math.add.mockReturnValue(1234);
    expect(subtract(5, 3)).toBe(1234);
    // 验证add是否被正确调用
    expect(math.add).toHaveBeenCalledWith(5, -3);
  });
});

原理说明

  1. jest.requireActual的作用:加载模块的真实代码,避免完全模拟丢失subtract的原始逻辑。
  2. ES模块的绑定特性:ES模块的导出是动态绑定的,当我们在模拟对象中重写add的导出时,模块内部subtract对add的引用会自动指向这个模拟函数——这正是常规spyOn无法做到的,因为spyOn只能拦截通过导出对象的属性访问,而模块内的直接调用原本绕过了导出对象。

为什么常规方法失效?

  • 直接覆写导入的add:ES模块的导出是只读的,无法直接赋值修改。
  • spyOn(math, 'add'):spyOn是替换导出对象的属性,但subtract内部调用的是模块本地定义的add函数,并非通过math.add引用,因此无法被拦截。

内容的提问来源于stack exchange,提问作者sstchur

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 18:05:38