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

Vue组合式函数测试:Mock内部函数失效问题求助

解决组合式函数内部函数Mock失效问题

问题根源

核心问题是闭包引用导致Mock不生效:onNodeChange内部调用的是useTreeData作用域内直接定义的saveTreeState函数,而非返回对象上的属性引用。你修改treeData.saveTreeState只是替换了返回对象的属性,完全不影响闭包内的函数调用逻辑。

解决方案

方案一:重构组合式(最简洁可靠)

将内部函数挂载到一个共享对象上,让onNodeChange通过该对象调用saveTreeState,这样返回对象的属性和内部引用指向同一个函数:

const useTreeData = () => {
  // 用对象包裹内部函数,实现共享引用
  const methods = {
    saveTreeState() {
      // does something
    }
  };

  function onNodeChange() {
    // 通过methods对象调用函数
    methods.saveTreeState();
  }

  return {
    ...methods,
    onNodeChange
  };
};

测试代码无需修改,替换treeData.saveTreeState即可生效:

const treeData = useTreeData();
treeData.saveTreeState = vi.fn();
treeData.onNodeChange();
expect(treeData.saveTreeState).toHaveBeenCalledOnce();

方案二:Mock整个组合式函数(无需重构原代码)

如果不想改动业务代码,可通过vi.doMock重写桶文件中的useTreeData实现,让它返回带有Mock函数的实例:

// 测试文件顶部
vi.doMock('@/path/to/your-bucket-file', async () => {
  // 保留桶文件中其他组合式的原实现
  const original = await vi.importActual('@/path/to/your-bucket-file');
  
  return {
    ...original,
    useTreeData: () => {
      // 创建Mock的saveTreeState
      const saveTreeState = vi.fn();
      // 重写onNodeChange,使其调用Mock函数
      const onNodeChange = () => {
        saveTreeState();
        // 若需保留原onNodeChange的其他逻辑,可调用原函数的对应逻辑
        // original.useTreeData().onNodeChange();
      };
      // 合并原组合式的其他返回属性
      const originalReturn = original.useTreeData();
      return {
        ...originalReturn,
        saveTreeState,
        onNodeChange
      };
    }
  };
});

// 测试用例
test('onNodeChange calls saveTreeState', async () => {
  const { useTreeData } = await import('@/path/to/your-bucket-file');
  const treeData = useTreeData();
  
  treeData.onNodeChange();
  expect(treeData.saveTreeState).toHaveBeenCalledOnce();
});

方案三:闭包捕获修改内部函数(进阶应急方案)

利用JavaScript闭包特性,借助返回的saveTreeState函数获取内部引用并替换:

test('onNodeChange calls saveTreeState', () => {
  const treeData = useTreeData();
  const spySave = vi.fn();

  // 获取闭包内saveTreeState的变量引用
  const saveTreeStateRef = Object.getOwnPropertyNames(treeData.saveTreeState)[0];
  // 替换闭包内的函数为Mock
  treeData.saveTreeState[saveTreeStateRef] = spySave;

  treeData.onNodeChange();
  expect(spySave).toHaveBeenCalledOnce();
});

注意:该方法依赖V8引擎的闭包存储实现,兼容性较差,仅作为临时应急方案使用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 11:15:06