依赖其他模块导出的函数
直接使用 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
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);
});
});