Write fast unit and integration tests with Vitest — vitest.config.ts setup, vi.fn and vi.mock module mocking, fake timers, snapshots, V8 coverage with thresholds, workspaces for monorepos, and in-source testing.
Standardmäßig ist der Prompt ausgewählt, der zuerst die Quelle prüft. Sie können zu einem direkten Befehl wechseln oder eine lokale Kopie herunterladen.
Quelldateien prüfen
Lesen Sie SKILL.md und alle von SkillsMP angezeigten Begleitdateien, bevor Sie sich für eine Installation entscheiden.
Mit Codex oder Claude installieren Kopieren Sie diesen Prompt, fügen Sie ihn in Codex, Claude oder einen anderen Assistant ein und lassen Sie die Skill-Seite prüfen und installieren.
Ein direkter Befehl überspringt den Prüf-Prompt. Prüfen Sie die Quelle, bevor Sie ihn ausführen.
Write fast unit and integration tests with Vitest — vitest.config.ts setup, vi.fn and vi.mock module mocking, fake timers, snapshots, V8 coverage with thresholds, workspaces for monorepos, and in-source testing.
This skill makes an AI agent write and configure Vitest test suites: a correct vitest.config.ts, module mocking with vi.mock and the vi.hoisted escape hatch, spies and fake timers, inline snapshots, V8 coverage gates, and projects config for monorepos. Trigger it on any Vite-based project, any repo with vitest in devDependencies, or when migrating from Jest.
Core Principles
Vitest reuses your Vite config — do not duplicate resolution logic. Aliases, plugins, and transforms from vite.config.ts apply to tests automatically. A separate Babel/transform setup is a Jest habit; drop it.
vi.mock is hoisted; factory variables are not. The mock factory runs before imports, so referencing top-level variables inside it throws. Use vi.hoisted() when the factory needs shared handles.
Prefer vi.fn injected via parameters over vi.mock of whole modules. Module mocking is a sledgehammer; dependency injection keeps tests honest and refactor-safe.
Inline snapshots over file snapshots for small values.toMatchInlineSnapshot puts the expectation in the test where reviewers see it; file snapshots get blindly --updated.
Coverage thresholds live in config and fail the run. A coverage report nobody gates on is wallpaper. Gate lines, functions, and branches — branch coverage is where the bugs hide.
Use the default node environment unless you render DOM.jsdom/happy-dom cost startup time per file; set them per-file with a docblock, not globally.
vitest run --project shared # one package
vitest run # everything, parallelized
In-source tests for small internal utilities (stripped from production builds by define: { 'import.meta.vitest': 'undefined' }):
// src/slug.tsexportfunctionslugify(input: string): string {
return input.toLowerCase().trim().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '');
}
if (import.meta.vitest) {
const { expect, it } = import.meta.vitest;
it('collapses punctuation runs into single hyphens', () => {
expect(slugify(' Hello, World! ')).toBe('hello-world');
});
}
Best Practices
Set restoreMocks: true globally instead of sprinkling vi.restoreAllMocks() in every afterEach.
Use vitest related src/pricing.ts in pre-commit hooks to run only tests touching changed files.
Assert promise rejections with await expect(p).rejects.toThrow(...) — a bare expect(p).rejects without await can pass before settlement.
Pin the environment per file when only some tests need DOM: // @vitest-environment jsdom at the top of the file.
Prefer test.each for input tables over copy-pasted tests; each row reports as its own case.
When migrating from Jest: vi replaces jest, vi.mock factories must return the module shape explicitly (no automock), and jest.requireActual becomes importOriginal.
Anti-Patterns
Referencing top-level variables inside a vi.mock factory. Hoisting makes them undefined at factory time — the error message mentions hoisting, believe it. Use vi.hoisted.
globals: true plus missing TS types. If you enable globals, add "types": ["vitest/globals"] to tsconfig, or imports break silently in editors.
Giant .toMatchSnapshot() on full API responses. Hundred-line snapshots get rubber-stamp updated. Snapshot small, stable slices; assert dynamic fields with matchers.
vi.mock of the module under test. You end up testing your own mock. Mock dependencies, never the subject.
Forgetting vi.useRealTimers() cleanup — fake timers leak into later tests and hang anything that genuinely waits.
Re-implementing Vite aliases inside test.alias when they already exist in vite.config.ts; drift between the two breaks resolution in tests only.
When to Trigger This Skill
The project is Vite-based or has vitest in devDependencies.
The user asks to add unit tests, mock a module, fake timers, or snapshot output in a TS/JS repo without Jest.
Setting up coverage gates or monorepo test projects with package-specific environments.
Migrating a Jest suite to Vitest (jest → vi API mapping, mock factory differences).
Tests fail with hoisting errors, environment mismatches, or leaking mocks — the classic Vitest misconfigurations.