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

如何在不修改导出结构的前提下测试函数x是否调用函数y?

你遇到的问题核心是:x内部调用的是模块本地的y函数,而非你导出的那个y引用。所以不管是vi.spyOn监听导出的y,还是单独创建mock函数,都影响不到x内部的调用逻辑。

下面给你几个不用大规模修改原代码的可行方案:

方案1:用Vitest模块mock改写导出逻辑

在测试里通过vi.mock提前替换模块导出的y为mock函数,同时让x指向调用这个mocky的逻辑(相当于间接复用原x的行为,但确保它用的是可监控的y):

import { x, y } from './你的模块文件路径'

vi.mock('./你的模块文件路径', () => {
  const actual = vi.importActual('./你的模块文件路径')
  // 用mock函数包裹原y的实现
  const mockY = vi.fn(actual.y)
  return {
    ...actual,
    y: mockY,
    // 让x调用mock的y,和原逻辑一致
    x: () => mockY()
  }
})

it('x 调用了 y', () => {
  x()
  expect(y).toBeCalledTimes(1)
})

方案2:用ESMock直接修改模块内部变量

如果不想改动测试里的x逻辑,可以用esmock工具直接替换模块内部的y引用,完全不用改原代码:

  1. 先装依赖:npm install esmock --save-dev
  2. 测试代码:
import esmock from 'esmock'

it('x 调用了 y', async () => {
  const mockY = vi.fn()
  // 加载模块时把内部的y替换成mock函数
  const { x } = await esmock('./你的模块文件路径', {}, {
    './你的模块文件路径': { y: mockY }
  })
  
  x()
  expect(mockY).toBeCalledTimes(1)
})

方案3:极小改动原代码(最省心)

如果能接受对原代码做一行微小修改,让x调用导出的y,那后续测试就简单了:

原代码修改:

export function y(){}
// 把原本的y()改成exports.y()(ES模块也可以用import * as self from './当前文件'; self.y())
export function x(){ exports.y() }

测试代码就能正常运行:

import * as t from './你的模块文件路径'

it('x 调用了 y', () => {
  const spy = vi.spyOn(t, 'y')
  t.x()
  expect(spy).toBeCalledTimes(1)
})

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 12:12:33