Write Tests for Existing Code
NEVER
- NEVER chain
mockResolvedValueOncewhenmockReset: true— the chain clears between tests. Use counter-basedmockImplementationinstead. - NEVER define mock variables at module scope then reference them inside
vi.mock()factories — hoisting creates a temporal dead zone. Usevi.hoisted()or globalThis registry. - NEVER
vi.importActual()for modules with side effects — use selective re-exports instead. - NEVER test implementation details (private state, internal call order) — test observable behavior through the public API.
- NEVER copy mock patterns from other projects — check YOUR test runner config first (
mockReset,mockClear,restoreMocks). - NEVER modify source code — this skill writes tests only; production behavior is fixed.
Before Writing, Ask Yourself
- Module type? Each has a different mock strategy (see table below).
- Blast radius? Does this module have side effects (DB writes, API calls, filesystem) that need isolation?
- Nearest test file? Find the closest
*.test.tsand match its exact mock structure — don't invent a new pattern.
Mock Strategy by Module Type
| Module Type | Strategy |
|---|---|
| Route handler | Test app builder + session simulation + app.inject() |
| Repository | Mock DB connection + counter-based execute |
| Framework plugin | Real framework instance + selective dependency mocks |
| Pure utility | No mocks — test inputs/outputs directly |
| Service w/ DI | Mock injected deps via forwarding pattern |
Mock Setup (mockReset: true)
If your test runner uses mockReset: true, most examples from the internet will silently fail — return values clear between tests.
const { mockFn } = vi.hoisted(() => ({
mockFn: vi.fn(),
}));
vi.mock("./dependency", () => ({
dependency: (...args: unknown[]) => mockFn(...args),
}));
beforeEach(() => {
// MUST reconfigure here — mockReset clears return values between tests
mockFn.mockResolvedValue(defaultResult);
});
For complex TDZ cases (multiple interdependent mocks), use the globalThis registry pattern:
vi.mock("./dep", () => {
if (!(globalThis as any).__mocks) (globalThis as any).__mocks = {};
const m = { dep: vi.fn() };
(globalThis as any).__mocks.dep = m;
return { dep: (...a: unknown[]) => m.dep(...a) };
});
// In tests: const mocks = (globalThis as any).__mocks;
Metacognitive Rule
If >3 tests fail on first run: STOP. Root cause is almost certainly a mock wiring issue affecting all tests — not individual test logic. Re-examine the mock setup holistically before fixing tests one by one.
Run
npx vitest run <test-file> --reporter=verbose
Arguments
$ARGUMENTS: Path to the source file or module to cover- Example:
/write-tests src/routes/admin/settings.ts - If empty: ask the user which file needs test coverage
- Example: