Key benefits of Vitest over Jest:
- 2-10x faster test startup (built on Vite and esbuild)
- Native TypeScript support without ts-jest
- Hot Module Replacement for instant re-runs
- Jest-compatible API requiring minimal code changes
- Modern ESM-first architecture
Option 1: vitest-codemod (recommended)
# Install globally
npm install -g @vitest-codemod/jest
# Run migration on test files
vitest-codemod jest path/to/tests/**/*.test.js
# Or use npx (no installation)
npx @vitest-codemod/jest path/to/tests
Option 2: Codemod.com Platform
# Using VS Code extension
# Install "Codemod" extension from marketplace
# Right-click project → "Run Codemod" → "Jest to Vitest"
# Using CLI
npx codemod jest/vitest
What codemods handle automatically:
- ✓ Convert
jest.mock()→vi.mock() - ✓ Convert
jest.fn()→vi.fn() - ✓ Convert
jest.spyOn()→vi.spyOn() - ✓ Convert
jest.setTimeout()→vi.setConfig({ testTimeout }) - ✓ Update global matchers and timer mocks
- ✓ Transform
jest.requireActual()→vi.importActual() - ✓ Update mock resets/clears/restores
1. Install Vitest
# Remove Jest
npm uninstall jest @types/jest ts-jest jest-environment-jsdom
# Install Vitest
npm install -D vitest @vitest/ui happy-dom
2. Create vitest.config.ts
import { defineConfig } from 'vitest/config'
export default defineConfig({
test: {
globals: true, // Enable globals for Jest compatibility
environment: 'happy-dom', // Faster than jsdom
setupFiles: ['./vitest.setup.ts'],
clearMocks: true,
restoreMocks: true,
},
})
3. Update package.json
{
"scripts": {
"test": "vitest",
"test:ui": "vitest --ui",
"test:run": "vitest run",
"test:coverage": "vitest run --coverage"
}
}
4. Update TypeScript config
{
"compilerOptions": {
"types": ["vitest/globals"]
}
}
5. Update mock syntax
// Replace in all test files:
jest.fn → vi.fn
jest.spyOn → vi.spyOn
jest.mock → vi.mock
jest.useFakeTimers → vi.useFakeTimers
jest.clearAllMocks → vi.clearAllMocks
Ready-to-run migration scripts available in scripts/ directory:
quick-migrate.sh- Fast 30-second migration for simple projectscomprehensive-migrate.sh- Full-featured migration with project detection, backups, and validation
See references/MIGRATION_SCRIPT.md for usage instructions.
jest.mock('./module', () => 'hello')
Vitest: Must specify exports explicitly
vi.mock('./module', () => ({
default: 'hello' // Explicit default export required
}))
Vitest: mockReset() resets to original implementation
To match Jest behavior in Vitest:
mockFn.mockReset()
mockFn.mockImplementation(() => undefined)
Vitest: Must explicitly enable:
export default defineConfig({
test: {
globals: true // Enable for Jest compatibility
}
})
Then add to tsconfig.json:
{
"compilerOptions": {
"types": ["vitest/globals"]
}
}
Vitest: Must call vi.mock() explicitly, or add to setupFiles:
// vitest.setup.ts
vi.mock('./path/to/module')
Vitest: Use async/await or Promises
// Before (Jest)
test('async test', (done) => {
setTimeout(() => {
expect(true).toBe(true)
done()
}, 100)
})
// After (Vitest)
test('async test', async () => {
await new Promise(resolve => {
setTimeout(() => {
expect(true).toBe(true)
resolve()
}, 100)
})
})
Solution: Manually import cleanup in setup file
// vitest.setup.ts
import { cleanup } from '@testing-library/react'
import { afterEach } from 'vitest'
afterEach(() => {
cleanup()
})
Solution: Configure in vitest.config.ts
import { defineConfig } from 'vitest/config'
import path from 'path'
export default defineConfig({
resolve: {
alias: {
'@': path.resolve(__dirname, './src'),
'@components': path.resolve(__dirname, './src/components'),
}
}
})
Solution: Vitest uses V8 by default. For Istanbul (Jest's provider):
npm install -D @vitest/coverage-istanbul
export default defineConfig({
test: {
coverage: {
provider: 'istanbul'
}
}
})
Jest: "describe title test title"
Vitest: "describe title > test title"
Solution: Regenerate snapshots with npm run test -u
- Use
happy-domoverjsdom- 2-3x faster for most use cases - Enable globals for easier migration - Set
globals: truein config - Use watch mode during development -
npm run test(default behavior) - Leverage UI mode for debugging -
npm run test:uiopens browser interface - Configure auto-cleanup - Set
clearMocks: trueandrestoreMocks: true - Use workspace configuration for monorepos - See CONFIG.md
export default defineConfig({
test: {
environment: 'node', // or 'happy-dom' instead of 'jsdom'
maxWorkers: 4, // Increase for parallel execution
fileParallelism: true,
testTimeout: 5000,
isolate: false, // Faster but use with caution
pool: 'threads', // or 'forks' for better isolation
}
})
Pool options:
threads(default) - Fast, CPU-intensive testsforks- Better isolation, more memoryvmThreads- Best for TypeScript performance
Prepare
- Ensure all Jest tests passing
- Commit working state
- Create migration branch
Install dependencies
npm install -D vitest @vitest/ui happy-domRun automated codemod
npx @vitest-codemod/jest src/**/*.test.tsCreate configuration
- Add
vitest.config.tswithglobals: true - Update
package.jsonscripts - Update
tsconfig.jsontypes
- Add
Run tests and fix issues
npm run test- Address failures one by one
- Check MIGRATION.md for solutions
Update CI/CD
- Replace Jest commands with Vitest
- Update coverage paths if needed
Cleanup
npm uninstall jest @types/jest ts-jest rm jest.config.js
npm run test # Watch mode
npm run test:run # Run once (CI mode)
npm run test:coverage # With coverage
npm run test:ui # Visual UI
npm run test path/to/file.test.ts # Specific file
npm run test -t "pattern" # Matching pattern
npm run test --environment jsdom # Specific environment
npm run test -u # Update snapshots
- MIGRATION.md - Complete Jest→Vitest API mapping, troubleshooting, framework-specific guides
- CONFIG.md - Full configuration reference with examples for React, Vue, TypeScript, Node.js, monorepos
- MIGRATION_SCRIPT.md - Automated migration script usage and customization
- Official Vitest docs: https://vitest.dev
- Vitest migration guide: https://vitest.dev/guide/migration
- vitest-codemod tool: https://github.com/trivikr/vitest-codemod
- Codemod platform: https://codemod.com/migrations/jest-to-vitest
- All tests passing with
npm run test:run - Coverage reports generate correctly
- CI/CD pipeline runs tests successfully
- No
jestreferences remain in codebase - TypeScript types resolve without errors
- Test execution is noticeably faster (2-10x improvement)
- 5x faster cold start - Initial test run (10s → 2s typical)
- 5x faster watch mode - Hot reload (5s → <1s typical)
- 2x faster execution - Overall test suite runtime
- 10x faster TypeScript tests - No ts-jest compilation overhead
- Better DX - Instant feedback, visual UI, better error messages