| name | writing-vitest-tests |
| description | Write Vitest tests with describe/test blocks, expect assertions, vi mocking, async testing, and parameterized tests. Use when creating or modifying test files. |
| allowed-tools | Read, Write, Edit, Bash, Grep, Glob |
Writing Vitest Tests
This skill teaches test structure and patterns for writing effective Vitest tests.
Quick Start
Basic Test
import { test, expect } from 'vitest';
test('adds numbers correctly', () => {
expect(1 + 2).toBe(3);
});
Test Suite
import { describe, test, expect } from 'vitest';
describe('Math utilities', () => {
test('adds numbers', () => {
expect(1 + 2).toBe(3);
});
test('subtracts numbers', () => {
expect(5 - 2).toBe(3);
});
});
For complete test organization patterns, see references/test-organization.md
Essential Assertions
Basic Matchers
expect(value).toBe(expected);
expect(value).toEqual(expected);
expect(value).toBeTruthy();
expect(value).toBeFalsy();
Arrays and Objects
expect(array).toContain(item);
expect(array).toHaveLength(3);
expect(object).toHaveProperty('key');
expect(object).toMatchObject({ key: 'value' });
Strings and Numbers
expect(string).toMatch(/pattern/);
expect(number).toBeGreaterThan(3);
expect(number).toBeCloseTo(0.3, 5);
For complete assertion API, see references/assertions.md
Mocking with vi
Mock Functions
import { vi, test, expect } from 'vitest';
test('calls callback', () => {
const callback = vi.fn();
callback('arg1', 'arg2');
expect(callback).toHaveBeenCalledWith('arg1', 'arg2');
expect(callback).toHaveBeenCalledTimes(1);
});
Mock Return Values
const mockFn = vi.fn();
mockFn.mockReturnValue('result');
expect(mockFn()).toBe('result');
Mock Implementation
const mockFn = vi.fn();
mockFn.mockImplementation((a, b) => a + b);
expect(mockFn(1, 2)).toBe(3);
For testing runtime type validation with Zod, use the using-runtime-checks skill for patterns on schema validation, error handling, and type inference.
Mock Promises
const mockFn = vi.fn();
mockFn.mockResolvedValue('data');
const result = await mockFn();
expect(result).toBe('data');
For testing code that validates external data with Zod, use the validating-external-data skill for patterns on API response validation, error handling, and type-safe validation flows.
For complete mocking patterns, see references/mocking.md
Module Mocking
Basic Module Mock
vi.mock('./module', () => ({
method: vi.fn(),
constant: 'mocked',
}));
Partial Module Mock
vi.mock(import('./module'), async (importOriginal) => {
const mod = await importOriginal();
return {
...mod,
specificMethod: vi.fn(),
};
});
For testing Zod validation of database inputs in Vitest, use the validating-query-inputs skill for patterns on Zod schema validation before Prisma operations.
Async Testing
Async/Await
test('fetches data', async () => {
const data = await fetchData();
expect(data).toBeDefined();
});
Promise Assertions
test('promise resolves', async () => {
await expect(fetchData()).resolves.toBe('data');
});
test('promise rejects', async () => {
await expect(fetchBadData()).rejects.toThrow('error');
});
Parameterized Tests
test.each with Arrays
test.each([
[1, 1, 2],
[1, 2, 3],
[2, 1, 3],
])('add(%i, %i) -> %i', (a, b, expected) => {
expect(a + b).toBe(expected);
});
test.each with Objects
test.each([
{ a: 1, b: 1, expected: 2 },
{ a: 1, b: 2, expected: 3 },
{ a: 2, b: 1, expected: 3 },
])('$a + $b should equal $expected', ({ a, b, expected }) => {
expect(a + b).toBe(expected);
});
For testing Zod schema validation in Vitest, use the testing-zod-schemas skill for patterns testing validation logic, error messages, and transformations.
Lifecycle Hooks
import { describe, test, beforeEach, afterEach, beforeAll, afterAll } from 'vitest';
describe('User service', () => {
beforeAll(() => {
});
afterAll(() => {
});
beforeEach(() => {
});
afterEach(() => {
});
test('creates user', () => {
});
});
Test Modifiers
test.skip('skipped test', () => {});
test.only('run only this test', () => {});
test.todo('implement later');
test.fails('should fail', () => {});
test.concurrent('runs in parallel', async () => {});
For testing Server Actions in isolation with Vitest, use the testing-server-actions skill for patterns on mocking authentication, database, and form data.
For testing form validation in React components with Vitest, use the validating-forms skill for patterns on form validation, useActionState, and error handling.
Timer Mocking
Fake Timers
import { vi } from 'vitest';
vi.useFakeTimers();
const callback = vi.fn();
setTimeout(callback, 1000);
vi.advanceTimersByTime(1000);
expect(callback).toHaveBeenCalled();
vi.useRealTimers();
Date Mocking
vi.setSystemTime(new Date(2022, 0, 1));
expect(Date.now()).toBe(new Date(2022, 0, 1).getTime());
vi.useRealTimers();
Snapshot Testing
test('matches snapshot', () => {
const result = generateOutput();
expect(result).toMatchSnapshot();
});
Update snapshots: vitest -u
Error Testing
test('throws error', () => {
expect(() => {
throw new Error('failed');
}).toThrow('failed');
});
test('async throws', async () => {
await expect(async () => {
throw new Error('failed');
}).rejects.toThrow('failed');
});
Fixtures
import { test as baseTest } from 'vitest';
const test = baseTest.extend({
todos: async ({}, use) => {
const todos = [];
await use(todos);
todos.length = 0;
},
});
test('adds item', ({ todos }) => {
todos.push('item');
expect(todos).toHaveLength(1);
});
For testing custom React hooks with Vitest, use the testing-hooks skill for renderHook patterns and hook-specific assertions.
Mock Cleanup
Per-Test Cleanup
import { afterEach, vi } from 'vitest';
afterEach(() => {
vi.restoreAllMocks();
});
Config-Based Cleanup
export default defineConfig({
test: {
restoreMocks: true,
clearMocks: true,
},
});
Component Testing
For testing React 19 components with Vitest browser mode, use the testing-components skill for patterns using @testing-library/react and handling useActionState, Server Actions, and React 19 hooks.
Best Practices
- One assertion per test: Keep tests focused
- Descriptive test names: Explain what is being tested
- AAA pattern: Arrange, Act, Assert
- Clean up mocks: Restore after each test
- Test behavior, not implementation: Focus on public API
- Avoid test interdependence: Tests should run independently
- Use fixtures for shared setup: Reduce duplication
Common Mistakes
- Not awaiting async operations: Use
async/await - Not cleaning up mocks: Use
afterEachor config options - Testing implementation details: Test public behavior
- Overly complex tests: Break into smaller tests
- Not using parameterized tests: Reduce duplication
References
For detailed testing patterns:
- Test Organization - Structure, hooks, fixtures, patterns
- Assertions - Complete matcher API reference
- Mocking - vi, modules, timers, globals
For configuration options, see @vitest-4/skills/configuring-vitest-4
For browser testing, see @vitest-4/skills/using-browser-mode
For complete API reference, see @vitest-4/knowledge/vitest-4-comprehensive.md