Skip to main content

依赖其他模块导出的函数

直接使用 vi.mock 来处理

比如下面代码,我们依赖了 ./user.js 文件中的 userAge 函数。

import { vi, it, expect } from vitest

// 自动提升
console.log(userAge()) // 2

vi.mock('./user', () => {
return {
userAge: () => 2, // 使用 userAge 替换掉了真实的 userAge 函数实现
}
})

it('* 2', () => {
const r = doubleUserAge()
expect(r).toBe(4)
})

it('other', () => {
// 全局生效
console.log(userAge()); // 2
})

我们将 ./user.js 文件里导出的 userAge 函数替换成了一个只会返回 2 的函数。

vi.mock 替换掉的东西会在该测试文件范围内,全局生效。

而且 vi.mock 会被自动提升到代码顶部。

避免全局生效和自动提升

以下两种办法都能避免被替换掉的东西在测试文件范围内全局生效,以及自动提升到代码顶部。

vi.mocked().mockReturnValue()

vi.mock() 也可以只接受一个 path,之后再进行 mock

import { userAge } from "./user";

vi.mock("./user");

describe("控制间接输入的值", () => {
it("* 2", () => {
vi.mocked(userAge).mockReturnValue(2);

const r = doubleUserAge();
expect(r).toBe(4);
});
});

这种方式允许我们在不同的测试 Case 里 mock 不同的值。

vi.doMock

vi.doMock() 官方文档

doMock 只在你下次执行 import 的时候才会生效。

// import { doubleUserAge } from "./index"; // removed

describe("控制间接输入的值", () => {
beforeEach(() => {
vi.doMock("./user", () => {
return {
userAge: () => 2,
};
});
});

it("* 2", async () => {
const { doubleUserAge } = await import("./index");

const r = doubleUserAge();
expect(r).toBe(4);
});
});

vi.doMock() 常和 beforeEach 结合使用。

异步获取数据

下面是一个异步获取数据的代码示例:

// userAge.ts
export async function fetchDoubleUserAge(): Promise<number> {
const userAge = await fetchUserAge();
return userAge * 2;
}
// api.ts
export function fetchUserAge(): Promise<number> {
return new Promise((resolve, reject) => {
setTimeOut(() => {
return resolve(18);
}, 0);
});
}
// userAge.spec.ts
vi.mock("./user", () => {
return {
fetchUserAge: () => Promise.resolve(2),
};
});

describe("控制间接输入的值", () => {
it("* 2", async () => {
const r = await fetchDoubleUserAge();
expect(r).toBe(4);
});
});