Vitest - Next Generation Testing Framework
Next generation testing framework powered by Vite for fast unit testing, component testing, and browser testing.
- Step 1
Overview
Vitest is a next-generation testing framework powered by Vite. It offers an intuitive developer experience with fast test execution, native code coverage, snapshot testing, and Jest-compatible APIs. Vitest is designed for modern web development with ESM-first architecture, top-level await, and out-of-the-box TypeScript and JSX support.
- Step 2
Technology Stack
Vitest is built with the following technologies:
Language: TypeScript License: MIT Stars: ~16,590 Owner: vitest-dev Repo: https://github.com/vitest-dev/vitest Website: https://vitest.dev Core Dependencies: - Vite (>=6.4.0) - Build tool and bundler - Node.js (>=22.12.0) - Runtime environment - Chai - Assertion library with Jest-compatible APIs - Jest Snapshot - Snapshot testing integration - JSDOM / Happy-DOM - DOM and browser API mocking - Tinybench - Benchmarking support - expect-type - Type-level testing Key Features: - Vite's config, transformers, resolvers, and plugins - Smart & instant watch mode (HMR for tests) - Native code coverage (v8 and Istanbul) - Jest-compatible mocking, stubbing, and spies - Browser Mode for component testing - Component testing (Vue, React, Svelte, Solid, Lit, Marko) - ESM first, top level await - Out-of-the-box TypeScript/JSX support - Step 3
Installation
Install Vitest using your preferred package manager.
npm install -D vitest yarn add -D vitest pnpm add -D vitest bun add -D vitest # For coverage pnpm add -D @vitest/coverage-v8 # For UI pnpm add -D @vitest/ui - Step 4
Basic Configuration
Vitest automatically detects and uses your Vite configuration.
// vitest.config.ts import { defineConfig } from 'vitest/config' export default defineConfig({ test: { include: ['src/**/*.test.{ts,js}'], exclude: ['**/node_modules/**', '**/dist/**'], environment: 'node', coverage: { provider: 'v8', reporter: ['text', 'json', 'html'] }, testTimeout: 5000, globals: true, watch: true } }) - Step 5
Running Tests
Run tests using npx or your package.json scripts.
npx vitest # Basic test run (watch mode) npx vitest run # Run without watch mode npx vitest run --coverage # Run with coverage npx vitest --ui # Run with UI npx vitest run -u # Update snapshots npx vitest run src/math.test.ts # Specific test file npx vitest --testNamePattern "should" # Filter by name - Step 6
Writing Tests
Create test files with .test.ts, .spec.ts, or .test.js extensions.
// math.test.ts import { describe, it, expect } from 'vitest' describe('Math operations', () => { it('adds numbers correctly', () => { expect(1 + 1).toBe(2) }) it('handles async operations', async () => { const result = await Promise.resolve(42) expect(result).toBe(42) }) it.skip('skipped test', () => {}) it.only('only runs this test', () => { expect(1).toBe(1) }) }) - Step 7
Using Matchers
Vitest provides matchers inspired by Jest and Chai.
import { describe, it, expect } from 'vitest' describe('Matchers', () => { it('equality', () => { expect(1).toBe(1) // Identity expect({ a: 1 }).toEqual({ a: 1 }) // Deep equality }) it('truthiness', () => { expect('hello').toBeTruthy() expect('').toBeFalsy() expect(null).toBeNull() }) it('types', () => { expect(42).toBeNumber() expect('text').toBeString() expect([1, 2]).toBeArray() }) it('arrays/strings', () => { expect([1, 2, 3]).toContain(2) expect('hello').toMatch(/ll/) }) it('async', async () => { await expect(Promise.resolve(1)).resolves.toBe(1) }) }) - Step 8
Mocking Functions
Use vi.fn() to create mock functions.
import { describe, it, expect, vi } from 'vitest' const mockFn = vi.fn() mockFn() mockFn(1) mockFn(1, 2) describe('Mock Functions', () => { it('tracks calls', () => { expect(mockFn).toHaveBeenCalledTimes(3) expect(mockFn).toHaveBeenCalledWith(1) }) it('mocks with implementation', () => { const mockFn = vi.fn((a, b) => a + b) expect(mockFn(1, 2)).toBe(3) }) it('async mocks', async () => { const mockFn = vi.fn().mockResolvedValue(42) expect(await mockFn()).toBe(42) }) }) - Step 9
Mocking Modules
Mock entire modules using vi.mock().
import { describe, it, expect, vi } from 'vitest' // Mock before importing vi.mock('./myModule', () => ({ fetchData: vi.fn().mockResolvedValue({ id: 1, name: 'test' }), processData: vi.fn((input: string) => input.toUpperCase()) })) describe('Mocked Module', () => { it('uses mocked implementation', async () => { const myModule = await import('./myModule') const data = await myModule.fetchData() expect(data).toEqual({ id: 1, name: 'test' }) }) }) // Unmock: vi.unmock('./myModule') // Partial: await vi.importActual('./myModule') - Step 10
Snapshot Testing
Vitest supports Jest-compatible snapshot testing.
import { describe, it, expect } from 'vitest' describe('Snapshots', () => { it('inline snapshot', () => { expect({ a: 1, b: 2 }).toMatchInlineSnapshot(` { "a": 1, "b": 2, } `) }) it('file snapshot', () => { expect({ foo: 'bar' }).toMatchSnapshot() }) }) # Update snapshots: npx vitest run -u - Step 11
Browser Mode
Run tests in real browsers with Playwright or WebDriverIO.
# Install browser testing pnpm add -D @vitest/browser playwright // vitest.config.ts export default defineConfig({ test: { browser: { enabled: true, headless: true, provider: 'playwright', instances: [{ browser: 'chromium' }] } } }) npx vitest --browser⚠ Heads up: Requires Playwright or WebDriverIO installed. - Step 12
Component Testing
Test Vue, React, Svelte components.
// Counter.test.ts import { mount } from '@vue/test-utils' import { describe, it, expect } from 'vitest' import Counter from './Counter.vue' describe('Counter', () => { it('renders initial count', () => { const wrapper = mount(Counter) expect(wrapper.text()).toContain('Count is 0') }) it('increments on click', async () => { const wrapper = mount(Counter) await wrapper.get('button').trigger('click') expect(wrapper.text()).toContain('Count is 1') }) }) - Step 13
Environments
Use different test environments.
// vitest.config.ts export default defineConfig({ test: { environment: 'jsdom', // or 'node', 'happy-dom', 'edge', 'browser' environmentOptions: { jsdom: { url: 'http://localhost', pretendToBeVisual: true } }, projects: [ { test: { name: 'node', environment: 'node', include: ['tests/node/**/*.test.ts'] } }, { test: { name: 'browser', environment: 'jsdom', include: ['tests/browser/**/*.test.ts'] } } ] } }) - Step 14
Test Coverage
Native code coverage through v8 or Istanbul.
pnpm add -D @vitest/coverage-v8 // vitest.config.ts export default defineConfig({ test: { coverage: { provider: 'v8', reporter: ['text', 'html', 'json'], thresholds: { global: { lines: 80, functions: 80 } } } } }) npx vitest run --coverage - Step 15
Watch Mode & Filtering
Smart watch mode and filtering.
npx vitest # Watch mode (default) npx vitest --testNamePattern "should" # Filter by name npx vitest src/auth.test.ts # Filter by file npx vitest --changed # Only changed tests npx vitest --no-file-parallelism # Sequential npx vitest --maxWorkers 4 # Limit workers - Step 16
Multi-project
Run tests across multiple projects.
// vitest.config.ts export default defineConfig({ test: { projects: [ { extends: './apps/api/vite.config.ts', test: { name: 'api', environment: 'node' } }, { extends: './apps/web/vite.config.ts', test: { name: 'web', environment: 'jsdom' } } ] } }) npx vitest --project api - Step 17
Vitest UI
Interactive browser UI for tests.
pnpm add -D @vitest/ui // vitest.config.ts export default defineConfig({ test: { ui: true, open: true } }) npx vitest --ui # Available at http://localhost:51204 - Step 18
Test Utilities (vi API)
Advanced control with vi utility.
import { vi } from 'vitest' vi.clearAllMocks() # Clear mocks vi.restoreAllMocks() # Restore mocks vi.resetModules() # Reset modules await vi.importActual('./module') # Import real vi.useFakeTimers() # Mock timers vi.advanceTimersByTime(1000) vi.setSystemTime(new Date('2024-01-01')) vi.stubEnv('NODE_ENV', 'test') # Stub env await vi.waitFor(() => expect(count.value).toBe(5), { timeout: 3000 }) - Step 19
Custom Matchers
Extend expect with custom matchers.
import { expect } from 'vitest' declare module 'vitest' { interface Assertion { toContainKey(key: string): void toBeEmptyArray(): void } } expect.extend({ toContainKey(received: object, key: string) { const pass = key in received return { message: () => `expected key`, pass } } }) expect({ a: 1 }).toContainKey('a') - Step 20
Key Features
Vitest capabilities:
1. Fast Execution: Vite-powered 2. Watch Mode: Smart HMR 3. Code Coverage: v8/Istanbul 4. Snapshot Testing: Jest-compatible 5. Browser Mode: Real browsers 6. Component Testing: Vue/React/Svelte 7. TypeScript: Native support 8. ESM First: Top-level await 9. Mocking: vi.* API 10. Projects: Multi-project 11. UI: Interactive runner 12. CI Friendly: Parallel 13. Benchmarking: Tinybench 14. Type Testing: expect-type 15. Extensible: Custom plugins - Step 21
Use Cases
Vitest is ideal for:
1. Unit Testing: Fast isolated tests 2. Component Testing: Framework components 3. Integration Testing: API mocking 4. Library Testing: Cross-framework 5. Microservices: Per-service tests 6. TypeScript: Native TS 7. Vite Projects: Zero-config 8. CI/CD: Fast parallel 9. Development: Instant feedback 10. Benchmarks: Performance 11. Coverage: Thresholds 12. Type-Safe: Runtime assertions 13. Browser: Real browser tests 14. ESM-only: Native ESM - Step 22
Migration from Jest
Migrate from Jest to Vitest:
Step 1: pnpm add -D vitest @vitest/ui Step 2: "test": "vitest" Step 3: jest.config.js -> vitest.config.ts Step 4: import "vitest", vi.fn(), vi.mock() Step 5: Matchers compatible Step 6: setupFiles / globalSetup Step 7: coverage provider: 'v8' - Step 23
Resources
Additional resources:
Documentation: https://vitest.dev GitHub: https://github.com/vitest-dev/vitest Discord: https://chat.vitest.dev API: https://vitest.dev/api/ Config: https://vitest.dev/config/ Migration: https://vitest.dev/guide/migration Examples: https://github.com/vitest-dev/vitest/tree/main/examples - Step 24
File Locations
Key files:
vitest.config.ts - Vitest config vite.config.ts - Vite config coverage/ - Coverage reports __snapshots__/ - Snapshots node_modules/.vitest/ - Cache
Feature requests
Sign in to suggest features or vote on existing ones.
No feature requests yet.
Discussion
Sign in to join the discussion.
No comments yet.