Vitest testing
Vitest testing patterns for production TypeScript projects. Use when writing tests, fixing test failures, configuring coverage, mocking modules, debugging flaky tests, or setting up Vitest in a monorepo. Covers Vitest 3+, vi.mock, vi.fn, React Testing Library, PGlite in-memory PostgreSQL, pool forks, maxWorkers, and hookTimeout.From its SKILL.md
npx -y skills add RevealUIStudio/revskills --skill vitest-testingAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 2 stars2 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
What its file declares
Copied from the file, not written here
The file declares its own license as MIT. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.
SKILL.md
4.2 KB, as published. Nobody here has run it
Vitest Testing Patterns
Test File Conventions
- Unit/integration tests:
*.test.tsor*.test.tsx(co-located with source) - Test directories:
__tests__/for grouped tests - Fixtures:
__fixtures__/ortest/fixtures/ - Test utilities: shared test package or
test/helpers.ts
Writing Tests
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
describe('MyFunction', () => {
it('should handle the happy path', () => {
const result = myFunction('valid-input');
expect(result).toEqual({ status: 'ok' });
});
it('should throw on invalid input', () => {
expect(() => myFunction('')).toThrow('Input required');
});
});
Mocking
// Mock a module
vi.mock('./database', () => ({
query: vi.fn().mockResolvedValue([{ id: 1 }]),
}));
// Mock a class (Biome-safe — use class syntax, not function)
vi.mock('./service', () => ({
MyService: class {
async getData() { return []; }
},
}));
// Spy on a method
const spy = vi.spyOn(object, 'method');
spy.mockReturnValue('mocked');
Important: When using Biome, always mock classes with class syntax inside vi.mock() factories. Biome converts function() to arrow functions, which breaks new.
Async Testing
it('should fetch data', async () => {
const result = await fetchData();
expect(result).toHaveLength(3);
});
it('should reject on error', async () => {
await expect(fetchBadData()).rejects.toThrow('Not found');
});
PGlite (In-Memory PostgreSQL)
import { PGlite } from '@electric-sql/pglite';
let db: PGlite;
beforeEach(async () => {
db = new PGlite(); // in-memory, fresh each test
await db.exec(schema);
});
afterEach(async () => {
await db.close();
});
Config for PGlite: PGlite startup can take 3-5s under load. Set hookTimeout: 30000 in vitest.config.ts:
export default defineConfig({
test: {
hookTimeout: 30000,
},
});
Monorepo Testing
// vitest.config.ts — per-package config
export default defineConfig({
test: {
pool: 'forks', // process isolation (not threads)
maxWorkers: 2, // prevent OOM in CI
hookTimeout: 30000, // PGlite startup time
include: ['src/**/*.test.{ts,tsx}'],
},
});
- Use
pool: 'forks'for process isolation (prevents shared state leaks) - Cap
maxWorkersto prevent fork explosion (turbo concurrency x workers = total processes) - Disable test caching in turbo (
"cache": falsein turbo.json test task) to prevent stale results
Coverage
// vitest.config.ts
export default defineConfig({
test: {
coverage: {
provider: 'v8',
reporter: ['text', 'lcov'],
exclude: ['**/*.test.ts', '**/__fixtures__/**'],
thresholds: {
statements: 80,
branches: 75,
functions: 80,
lines: 80,
},
},
},
});
Common Mistakes to Avoid
- Don't use
jest.fn()— usevi.fn()(Vitest, not Jest) - Don't mock everything — prefer real implementations, mock only external services
- Don't use
function()invi.mock()factories — Biome converts to arrows, breakingnew - Don't share state between tests — use
beforeEachto reset - Don't use threads pool with native modules — use
forks - Don't set
hookTimeouttoo low when using PGlite
Debugging Flaky Tests
- Check for shared mutable state between tests
- Check for timing issues (
setTimeout,setInterval) - Check for port conflicts (parallel workers binding same port)
- Check for PGlite startup timeout under load
- Run with
--reporter=verboseto see individual test timings - Run single test:
vitest run src/path/to/file.test.ts
Skill by RevealUI Studio — the agentic business runtime.