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

直接调用函数与通过exports对象调用的差异及Jest Mock问题解析

为什么Jest Mock函数b后,函数a调用b()不生效但调用exports.b()生效?

核心原因:模块内部函数引用 vs 导出对象的函数引用差异

1. 原始代码中a()直接调用b()的情况

你的Module.js里,function b()是定义在模块作用域内的局部函数,a()直接调用的是这个局部的b函数。当你用export {a, b}导出时,本质是把b函数的引用复制到了模块的导出对象上(ES模块里是创建导出绑定,行为类似)。

Jest的jest.spyOn(module, 'b')操作的是导出对象上的b引用,但模块内部a()调用的还是原来的局部b函数——两者是独立的引用,所以Mock不会影响a()的执行结果。

用代码逻辑拆解:

// Module.js 实际执行逻辑简化
const b = function() { return 'b'; };
const a = function() { return b(); }; // 这里的b是指向原始函数的局部变量

// 导出时,把b的引用复制到导出对象
module.exports.b = b;
module.exports.a = a;

当你在测试中jest.spyOn(module, 'b').mockReturnValue('c'),只是把module.exports.b的引用换成了Mock函数,但a()内部还是调用原来的b,所以返回值还是'b'。

2. 修改为exports.b()后的情况

当你把a()内部的调用改成exports.b()(或ES模块里的import * as self from './Module.js'; self.b()),此时a()调用的是导出对象上的b函数引用。

这时候Jest的spyOn修改的正是这个导出对象上的b引用,所以当a()执行时,会直接调用Mock后的函数,返回预期的'c'。

逻辑拆解:

// 修改后的Module.js 逻辑简化
const b = function() { return 'b'; };
const a = function() { return module.exports.b(); }; // 直接引用导出对象上的b

module.exports.b = b;
module.exports.a = a;

测试中Mockmodule.exports.b后,a()调用的就是Mock函数,返回'c'。

两种调用方式的核心差异总结

  • 直接调用b():使用模块作用域内的原始函数引用,和导出对象上的引用相互独立,Mock导出的函数不会影响内部调用。
  • 调用exports.b():直接使用导出对象上的函数引用,Mock操作会直接覆盖这个引用,内部调用会同步使用Mock后的函数。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 14:47:34