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

在Jest中是否可以mock同一模块内部被其他函数调用的函数?

问题根因

当前写法失效的核心是foo.ts中foo()调用的是模块内部作用域的原始bar函数引用,而jest.spyOn只能修改导出的模块对象上的bar属性指向,两者不属于同一个引用,因此内部调用不会触发你设置的mock逻辑。

可行解决方法

方案1:调整内部调用指向导出对象(侵入性极低,推荐)

只需修改foo.ts中foo的调用逻辑,让它指向导出的模块对象上的bar,即可兼容原测试代码,TS项目推荐这种写法:

// foo.ts
import * as currentModule from './foo'

export function bar(){
  throw 'not implemented'
}

export function foo(){
  // 调用导出对象上的bar,而非内部作用域的bar
  return currentModule.bar()
}

原测试代码无需修改即可正常运行。

方案2:将函数封装到对象中导出

如果你的函数本身就适合分组封装,可以把相关函数放到统一对象中导出,利用this指向实现可mock:

// foo.ts
export const fooUtils = {
  bar() {
    throw 'not implemented'
  },
  foo() {
    return this.bar()
  }
}

测试代码调整为:

// foo.test.ts
import { fooUtils } from './foo'

test('TODO', () => {
  jest.spyOn(fooUtils, 'bar').mockReturnValue('quux')
  expect(fooUtils.foo()).toBe('quux')
});

方案3:使用rewire能力修改内部变量(无业务代码侵入)

如果完全不想修改原业务代码,可以借助ts-jest内置的rewire能力直接修改模块内部的bar引用:

  1. 先在jest.config.js中开启rewire支持:
module.exports = {
  // 其余配置保持不变
  transform: {
    '^.+\\.tsx?$': ['ts-jest', {
      rewire: true
    }]
  }
}
  1. 调整测试代码:
// foo.test.ts
import * as fooModule from './foo'

test('TODO', () => {
  fooModule.__set__('bar', jest.fn().mockReturnValue('quux'))
  expect(fooModule.foo()).toBe('quux')
})

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.06 03:24:00