Vitest Testing Guidelines
For framework-independent test design: Arrange-Act-Assert, FIRST, and choosing/naming test doubles, see testing-guide; this guide covers only Vitest-specific mechanics.
Requirements
- Vitest ≥ 3, TypeScript ≥ 5.8
Essentials
- Type safety - Cast
res.json()to declared interfaces, see references/type-safety.md - HTTP testing - Assert the status the middleware actually sends, see references/http-testing.md
- Timestamp testing - Avoid flaky comparisons; verify existence or add delays, see references/timestamp-testing.md
- TypeScript config - Include test paths; verify project reference levels, see references/typescript-config.md
- Test organization - Mirror API structure under
test/with nested describe blocks, see references/test-organization.md
Gotchas
- Vitest transforms (
vite-node) differ from Jest:__dirname/__filenamework in CommonJS but not ESM tests without polyfills vi.spyOnreturns the spy;vi.fncreates a new mock: confusing them passes type checks but breaks call-tracking assertionsexpect.assertions(n)in async tests catches missed awaits, without it, a forgottenawaitlets the test pass spuriously- Watch mode caches module graphs; changing
vitest.config.tsrequires a full restart to pick up new transforms
Progressive disclosure
- Read references/type-safety.md - Load when calling
res.json()or test variables lose type information - Read references/http-testing.md - Load when asserting HTTP status codes or testing CORS OPTIONS requests
- Read references/timestamp-testing.md - Load when tests fail intermittently due to timing
- Read references/mock-patterns.md - Load when creating mocks or stubs for tests
- Read references/typescript-config.md - Load when test files aren't recognized by TypeScript or reference imports fail
- Read references/test-organization.md - Load when structuring test suites for large APIs