vitest-mocking

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.

$ 安裝

git clone https://github.com/alexanderop/workoutTracker /tmp/workoutTracker && cp -r /tmp/workoutTracker/.claude/skills/vitest-mocking ~/.claude/skills/workoutTracker

// tip: Run this command in your terminal to install the skill


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

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)

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

Use stubGlobal when: Replacing browser/Node globals

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

Essential Patterns

Mock Module (hoisted)

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

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

Mock with Implementation

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

Spy with Fake Return

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

Mock Global Fetch

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

Fake Timers

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

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

Clean Up

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.