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

Vitest如何Mock被测试函数所调用的内部函数?

如何Mock模块内的函数并让实际函数调用Mock版本?

我想Mock hello 函数并使用.mockReturnValue("Hi "),但运行测试后仍返回Hello John,且hello函数未被调用。请问如何在实际的greet函数中Mockhello()的实现?

示例代码:

// greet.ts
export function hello() {
  return "Hello ";
}

export function greet(name: string) {
  return hello() + name;
}

测试文件:

// greet.spec.ts
import {hello, greet} from "./greet";

vi.mock("./greet", async () => {
  const mod = await vi.importActual<typeof import("./greet")>("./greet");
  const hello = vi.fn().mockReturnValue("Hi ");
  return {
    ...mod,
    hello,
    // greet: vi.fn((name: string)=> hello() + name),
    // ^取消注释后可用,但违背测试目的
    // 难道我想要的效果无法实现?
  }
})

describe("Greeting", () => {
  test("should return a personalized greeting", async () => {
    const result = greet("John");

    expect(result).toBe("Hi John");
    expect(hello).toHaveBeenCalled();
  });
});

问题原因

核心问题在于:greet函数内部直接调用的是模块内本地定义的hello函数,而非你通过vi.mock替换的导出版本。ES模块中,内部函数的引用是闭包绑定,不会自动关联到导出的Mock函数。

解决方案

方案1:调整原代码的引用方式(推荐)

修改greet.ts,让greet通过模块自身的导出引用hello,这样Mock的导出函数就能被实际调用:

// greet.ts
import * as self from './greet';

export function hello() {
  return "Hello ";
}

export function greet(name: string) {
  // 改为调用导出的hello函数
  return self.hello() + name;
}

此时你原来的测试代码无需修改,运行测试就能得到Hi John的预期结果,且helloMock函数会被正确调用。

方案2:在Mock中重写greet逻辑(无需修改原代码)

如果无法调整原代码,可以在vi.mock中重新定义greet函数,让它依赖Mock的hello,同时复用原函数的逻辑:

// greet.spec.ts
import { hello, greet } from "./greet";

vi.mock("./greet", async () => {
  const actual = await vi.importActual<typeof import("./greet")>("./greet");
  const mockHello = vi.fn().mockReturnValue("Hi ");
  return {
    ...actual,
    hello: mockHello,
    // 重新实现greet,使用mock的hello
    greet: (name: string) => mockHello() + name
  };
});

describe("Greeting", () => {
  test("should return a personalized greeting", () => {
    const result = greet("John");
    expect(result).toBe("Hi John");
    expect(hello).toHaveBeenCalled();
  });
});

这种方式无需改动原代码,适合不能修改源代码的场景,虽然需要重写greet的逻辑,但能达到测试目的。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 06:25:36