vitest-mocking
Vitest Mocking
Test Double Types
| Type | Purpose | Changes Implementation? |
|---|---|---|
| Spy | Record calls, verify interactions | No (uses real code) |
| Mock | Replace module entirely | Yes |
| Stub | Return canned responses | Yes |
| Fake | Working but simplified impl | Yes |
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.
More from alexanderop/workouttracker
vue-composables
Write high-quality Vue 3 composables following established patterns and best practices. Use when creating new composables, refactoring existing ones, or reviewing composable code. Triggers include requests to "create a composable", "write a use* function", "extract logic into a composable", or any Vue Composition API reusable logic task.
23product-planning
|
19add-exercises
Add new exercises to the workout tracker database. Use when asked to add exercises, expand the exercise library, or check what exercises exist. Triggers include "add exercise", "new exercise", "exercise database", "what exercises", "missing exercises", "expand exercises".
12systematic-debugging
|
12repository-pattern
Create and manage Dexie/IndexedDB repositories with type-safe interfaces, converters, and standardized CRUD operations. Use when (1) adding entity storage, (2) implementing save/load/delete operations, (3) designing database schema and indexes, (4) converting between database (Db*) and domain types, (5) handling database errors or migrations, (6) using existing repositories (SettingsRepository, WorkoutsRepository, TemplatesRepository, CustomExercisesRepository, BenchmarksRepository, ActiveWorkoutRepository). Triggers include "database", "repository", "save data", "fetch from database", "delete from storage", "database schema", "database table", "indexes", "migration", "persist", "convert workout", "converter", "buildPartialUpdate", "mock repository", "database error", "bulk operations", "import/export", or specific repository names.
12improve-skill
Analyze coding agent session transcripts to improve existing skills or create new ones. Use when asked to improve a skill based on a session, or extract a new skill from session history.
11