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

Jest中spyOn调用mockImplementation仍执行原方法的原因咨询

问题根本原因

第一种测试写法mock的实例和业务代码实际使用的实例不是同一个对象,mock自然不会生效。

执行逻辑拆解

  • 业务代码的实例初始化在模块加载阶段就已完成:当你在测试代码中引入业务模块时,业务模块顶层的const emailModule = new SomeEmailModule()会立刻执行,生成的实例会一直保存在业务模块的作用域中,sendEmail函数后续调用的永远是这个提前生成的实例的send方法。
  • 第一种测试写法的问题:你在测试用例内部执行const emailModule = new SomeEmailModule()是新生成了另一个完全独立的实例,你用jest.spyOn修改的是这个新实例自身的send方法,对业务模块里早就创建完成的旧实例没有任何影响,所以实际执行时还是走原生方法逻辑。

后两种写法生效的底层逻辑

JS 中类的实例方法默认挂载在构造函数的原型对象上,只要实例自身没有单独重写这个方法,调用时会沿着原型链向上查找到构造函数prototype上的对应方法。

  • 直接修改SomeEmailModule.prototype.send相当于修改了所有实例共享的方法源头,不管是业务代码提前生成的旧实例,还是后续新生成的实例,调用send时都会走到你mock的版本。
  • 用jest.spyOn(SomeEmailModule.prototype, 'send')(注:你写法里的spyOne是笔误,正确为spyOn)的逻辑和直接修改原型一致,只是jest封装了备份原始方法、测试结束后可一键还原的能力,底层都是修改原型上的公共方法。

补充:其他可行的mock方案

如果不想修改原型,也可以直接mock整个SomeEmailModule的导出,让所有实例化操作都返回带mock方法的对象:

const mockSend = jest.fn()
jest.mock('SomeEmailModule', () => {
  return jest.fn().mockImplementation(() => ({
    send: mockSend
  }))
})

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 14:45:03