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

为何Jest Spy在被测文件解构导入被监视函数时失效?

为什么Jest的Spy无法监视解构导入的函数?

问题场景

测试文件代码:

const webhook = require('../../../../../../src/lib/apis/webhook');

const internalFunc = jest.spyOn(webhook, 'handleWebhookCreation').mockImplementation(() => {
   return expectedReturn;
});

被测文件原始代码:

const { handleWebhookCreation } = require('../../../apis/webhook');

const createWebhook = async (req, res) => {
    for (const webhook of payload) {
      results.push(await handleWebhookCreation(webhook, t));
    }
};

上述代码无法正常工作,调用的是原函数而非被模拟/监视的版本。

解决方法

修改被测文件,不使用解构导入,而是导入整个模块对象,再调用其中的方法:

const _webhook = require('../../../apis/webhook');
// ...
results.push(await _webhook.handleWebhookCreation(webhook, t));

此时单元测试中的Spy/模拟可以正常工作。

原因解释

这本质是模块导出的引用机制和解构赋值的行为共同导致的:

  • 当你用const { handleWebhookCreation } = require('xxx')解构导入时,相当于把模块导出对象里handleWebhookCreation属性对应的原始函数引用,复制到了当前文件的handleWebhookCreation变量中。这个变量和原导出对象的属性彻底解绑,后续导出对象的属性变化不会影响它。
  • Jest的spyOn方法是通过修改模块导出对象上的目标属性,把原函数替换成模拟函数。但被测文件里的handleWebhookCreation变量依然指向最初复制的原始函数,所以调用时不会触发模拟逻辑。
  • 改成通过模块对象调用_webhook.handleWebhookCreation时,每次都会从模块导出对象上读取该属性,这时候读到的就是被Jest替换后的模拟函数,因此能正常生效。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 01:31:07