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

如何使用Jest Mock带参数的函数?Mock不生效原函数仍执行如何解决?

问题根因

  1. 导入时序错误
    ES 模块的导入语句存在提升特性,会在所有代码执行前先完成导入。你在测试代码中先导入了<AddForm/>组件,此时B.js已经提前导入并持有了原始add方法的引用,后续你对A.js的 mock 操作无法影响已经被B.js捕获的函数引用,因此调用的还是原生方法。
  2. 导出导入不匹配
    你提供的A.js中使用的是export add命名导出,而B.js中使用import add from './A'默认导入,本身存在语法错误,需要先统一两者的导出导入规则。

修复步骤

第一步:统一导出导入规则

二选一即可:

  • 方案A:将A.js改为默认导出
// A.js
function add(a, b, c) {
  return a + b + c
}
export default add;
  • 方案B:将B.js改为命名导入
// B.js
import { add } from './A';

第二步:修正测试代码

推荐使用jest.mock方案,不受导入提升影响,稳定性更高:

// B.test.js
// 这行代码会被jest自动提升到所有导入之前执行,优先完成mock
jest.mock('./A', () => ({
  // 如果是命名导出,替换为 add: jest.fn(() => 100)
  default: jest.fn(() => 100)
}))
import AddForm from './B';
// 如果是命名导出,替换为 import { add } from './A'
import add from './A';

describe('<AddForm/>', () => {
  test('should call add with correct parameters', () => {
    render(<AddForm />);
    // 验证add被调用参数符合预期
    expect(add).toHaveBeenCalledWith(1, 2, 3);
    // 验证mock返回值生效
    expect(add.mock.results[0].value).toBe(100);
  });
});

如果需要保留jest.spyOn的写法,需要用require手动控制导入时序,避免导入提升的影响:

// B.test.js
const helpers = require('./A');
// 如果是命名导出,把'default'改为'add'
const addSpy = jest.spyOn(helpers, 'default').mockImplementation(() => 100);
const AddForm = require('./B').default;

describe('<AddForm/>', () => {
  afterEach(() => {
    addSpy.mockRestore();
  });

  test('should render all elements', () => {
    render(<AddForm />);
    expect(addSpy).toHaveBeenCalledWith(1,2,3);
  });
});

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 23:54:06