AgentSkillsCN

vitest-mocking

Vitest模拟模式和测试双策略。当编写需要模拟、存根、stub或fake的测试时使用。触发包括:模拟模块、stub全局(fetch、Date、定时器)、测试组合式、模拟导入(默认/命名)、创建测试双、替换依赖、验证模拟调用、清理模拟,或任何关于“如何在Vitest中模拟X”的问题。在审查测试以确保正确模拟实践时也使用。

SKILL.md
--- frontmatter
name: vitest-mocking
description: |
  Vitest mocking patterns and test double strategies. Use when writing tests that need mocks, spies, stubs, or fakes. Triggers include: mocking modules, stubbing globals (fetch, Date, timers), testing composables, mocking imports (default/named), creating test doubles, replacing dependencies, verifying mock calls, cleaning up mocks, or any question about "how do I mock X in Vitest". Also use when reviewing tests for proper mocking practices.

Vitest Mocking

Test Double Types

TypePurposeChanges Implementation?
SpyRecord calls, verify interactionsNo (uses real code)
MockReplace module entirelyYes
StubReturn canned responsesYes
FakeWorking but simplified implYes

Decision Guide

Use spy when: Verifying a function was called correctly while keeping real behavior

ts
const fetchSpy = vi.spyOn(globalThis, "fetch");
await doSomething();
expect(fetchSpy).toHaveBeenCalledWith("https://api.example.com");

Use mock when: Replacing external dependencies (network, database, third-party modules)

ts
vi.mock("./api-client");
vi.mocked(apiClient.fetch).mockResolvedValue({ data: "test" });

Use stubGlobal when: Replacing browser/Node globals

ts
vi.stubGlobal("fetch", vi.fn().mockResolvedValue(mockResponse));

Essential Patterns

Mock Module (hoisted)

ts
import { someFunc } from "./module";
vi.mock("./module"); // hoisted to top

it("test", () => {
  vi.mocked(someFunc).mockReturnValue("mocked");
});

Mock with Implementation

ts
vi.mock("./module", () => ({
  someFunc: vi.fn().mockReturnValue("mocked"),
}));

Spy with Fake Return

ts
const spy = vi.spyOn(obj, "method").mockReturnValue("fake");

Mock Global Fetch

ts
globalThis.fetch = vi.fn().mockResolvedValue({
  ok: true,
  json: async () => ({ data: "test" }),
} as Response);

Fake Timers

ts
beforeAll(() => vi.useFakeTimers());
afterAll(() => vi.useRealTimers());

it("test", async () => {
  // advance time
  await vi.advanceTimersByTimeAsync(5000);
});

Clean Up

ts
beforeEach(() => vi.clearAllMocks()); // reset call counts
afterEach(() => vi.restoreAllMocks()); // restore originals

Reference

For complete examples including default imports, named imports, classes, partial mocks, snapshot testing, composables, and verification patterns, see references/cheat-sheet.md.