Vitest Unit Testing Tutorial: A Complete 2026 Guide
Jul 27, 2026 4 Min Read 25 Views
(Last Updated)
Vitest unit testing framework is built on top of Vite that lets JavaScript and TypeScript projects run tests using the same fast build pipeline as their dev server. Install it with npm install -D vitest, write tests using describe, it, and expect (the same syntax Jest uses), and run them with npx vitest. Because it reuses Vite’s transform engine, test startup and re-runs are typically much faster than traditional Jest setups, especially in projects already using Vite.
Table of contents
- TL;DR Summary
- What Is Vitest?
- Why Developers Are Switching to Vitest
- Setting Up Vitest in a Project
- Writing Your First Test
- Mocking Functions and Modules
- Measuring Test Coverage
- Vitest vs Jest: A Quick Comparison
- Key Takeaways
- Conclusion
- FAQs
- Q1: Is Vitest a replacement for Jest?
- Q2: Does Vitest work with React and Vue?
- Q3: Can I use Jest matchers in Vitest?
- Q4: Do I need a separate config file for Vitest?
- Q5: How do I check test coverage in Vitest?
- Q6: Is Vitest slower or faster than Jest?
TL;DR Summary
- Vitest is a Vite-native test runner built for speed, with a Jest-compatible API so most teams migrate in hours, not weeks.
- It runs natively on ESM and TypeScript without extra transpilation config, which is where most Jest setups lose time.
- You get watch mode, a browser-based UI (vitest –ui), snapshot testing, and built-in mocking via the vi object.
- Coverage reporting works out of the box through v8 or istanbul providers — no separate babel plugin needed.
- This guide walks through installation, your first test, mocking, coverage, and how Vitest compares to Jest.
What Is Vitest?
Vitest is an open-source unit testing framework created by the Vite team (led by Anthony Fu and collaborators) to solve a specific frustration: most JavaScript projects in 2026 build with Vite, but test with Jest a tool that uses a completely different transform pipeline underneath.
That mismatch means double config. You set up Babel or ts-jest for Jest, separately from whatever Vite is already doing for your app code. Vitest collapses that into one pipeline. It reads your existing vite.config.ts, reuses Vite’s plugins, and runs your tests through the same engine that serves your dev server.
Pro Tip: If your project already has a vite.config.ts, you can usually add a test block to that same file instead of creating a separate Vitest config — one less file to maintain.
Why Developers Are Switching to Vitest
A few reasons keep coming up when teams move off Jest:
- Native ESM support. No babel-jest transform step for ES modules.
- TypeScript out of the box. No ts-jest setup, no separate tsconfig for tests.
- Jest-compatible API. describe, it, test, expect, beforeEach — the syntax most developers already know transfers directly.
- Built-in UI mode. Running vitest –ui opens a browser dashboard showing test results, file trees, and console output, which is genuinely useful when debugging a flaky test rather than reading raw terminal output.
- Watch mode by default. Tests re-run automatically and only re-execute files affected by your latest change.
Setting Up Vitest in a Project
Here’s the basic install and config flow for a typical Vite-based project.
Step 1 — Install Vitest
npm install -D vitest
Step 2 — Add a test script
In package.json:
"scripts": {
"test": "vitest"
}
Step 3 — Configure (optional but recommended)
If you don’t already have a vite.config.ts, create vitest.config.ts:
import { defineConfig } from 'vitest/config'
export default defineConfig({
test: {
globals: true,
environment: 'jsdom', // use 'node' for backend-only projects
},
})
Setting globals: true means you don’t need to import describe, it, and expect in every file — they’re available globally, similar to Jest’s default behavior.
Warning: If you’re testing browser-facing code (DOM manipulation, React/Vue components), you need environment: ‘jsdom’ or environment: ‘happy-dom’. Without it, Vitest runs in a plain Node environment with no document or window object, and DOM-related tests will fail immediately.
Writing Your First Test
Say you have a simple utility function:
// sum.ts
export function sum(a: number, b: number): number {
return a + b
}
Your test file sits alongside it:
// sum.test.ts
import { describe, it, expect } from 'vitest'
import { sum } from './sum'
describe('sum()', () => {
it('adds two positive numbers', () => {
expect(sum(2, 3)).toBe(5)
})
it('handles negative numbers', () => {
expect(sum(-1, -1)).toBe(-2)
})
})
Run it:
npx vitest run
Or stay in watch mode during development:
npx vitest
Vitest will re-run sum.test.ts automatically every time sum.ts or the test file changes.
Mocking Functions and Modules
Vitest ships its own mocking utilities through the vi object, replacing Jest’s jest.fn() and jest.mock().
Mocking a function:
import { vi, it, expect } from 'vitest'
const mockFn = vi.fn().mockReturnValue(42)
it('returns the mocked value', () => {
expect(mockFn()).toBe(42)
})
Mocking a whole module:
import { vi } from 'vitest'
vi.mock('./api', () => ({
fetchUser: vi.fn().mockResolvedValue({ id: 1, name: 'Test User' }),
}))
Spying on an existing method:
const spy = vi.spyOn(console, ‘log’)
console.log(‘hello’)
expect(spy).toHaveBeenCalledWith(‘hello’)
This is one of the few areas where teams migrating from Jest hit small syntax differences — the concepts map closely, but vi replaces jest as the namespace everywhere.
Measuring Test Coverage
Vitest has coverage built in through two providers: v8 (default, faster, uses Node’s native coverage) and istanbul (more configurable, slightly slower).
Install the provider:
npm install -D @vitest/coverage-v8
Run with coverage:
npx vitest run –coverage
This generates a terminal summary plus an HTML report (typically in a coverage/ folder) showing line, branch, function, and statement coverage per file.
Vitest vs Jest: A Quick Comparison
| Feature | Vitest | Jest |
|---|---|---|
| Build engine | Vite (esbuild/Rollup) | Babel / ts-jest |
| Native ESM | Yes | Partial, needs config |
| Native TypeScript | Yes | Needs ts-jest or Babel preset |
| API syntax | Jest-compatible | Original |
| Watch mode | Default, fast HMR-style reruns | Available, generally slower startup |
| UI dashboard | Built-in (vitest –ui) | Requires third-party tools |
| Best fit | Vite-based projects (React, Vue, Svelte via Vite) | Projects already deep in the Jest/Babel ecosystem, or non-Vite setups |
Jest remains a solid, mature choice — especially for teams not using Vite, or with large existing Jest suites where migration cost outweighs the speed gain. Vitest’s advantage is sharpest specifically when your app already builds with Vite.
Key Takeaways
- Vitest reuses your Vite config, so there’s no separate transform pipeline to maintain alongside your app’s build setup.
- The describe/it/expect API is close enough to Jest that most existing test files need minimal changes to run.
- vi.fn(), vi.mock(), and vi.spyOn() cover the same mocking needs as Jest’s jest.* utilities.
- Coverage works out of the box via @vitest/coverage-v8, with no Babel plugin required.
- Vitest makes the most sense for Vite-based projects; teams on other build tools should weigh migration cost against the speed benefit.
If you want a structured, mentor-supported path through everything in a roadmap, HCL GUVI’s IIT-M Pravartak Certified Full Stack Developer Course with AI Integration covers the entire journey, from HTML to deployment, with real projects, live sessions, and placement support. Over 10,000 students have used it to break into product-based companies.
Conclusion
Vitest isn’t a reinvention of unit testing — it’s a faster, more native fit for projects already built on Vite, with an API close enough to Jest that the learning curve is shallow. Whether you should switch your existing test suite depends mostly on your current build tool, but if you’re starting a new project on Vite, there’s little reason to reach for anything else.
Ready to add Vitest to your own project? Start with the official Vitest Getting Started guide and run your first test today.
FAQs
Q1: Is Vitest a replacement for Jest?
Vitest can replace Jest in most projects, especially those already using Vite. It isn’t a strict requirement, but it removes the need for separate Babel/ts-jest configuration.
Q2: Does Vitest work with React and Vue?
Yes. Vitest works with any framework Vite supports, including React, Vue, Svelte, and Solid, as long as you set the correct environment (like jsdom) for DOM testing.
Q3: Can I use Jest matchers in Vitest?
Yes. Vitest’s expect API is built to be Jest-compatible, so most common matchers like toBe, toEqual, and toHaveBeenCalledWith work without changes.
Q4: Do I need a separate config file for Vitest?
No, if you already have a vite.config.ts. You can add a test property directly to that existing config instead of creating a new file.
Q5: How do I check test coverage in Vitest?
Install @vitest/coverage-v8, then run npx vitest run –coverage. This generates both a terminal summary and an HTML report.
Q6: Is Vitest slower or faster than Jest?
Vitest is generally faster in Vite-based projects because it reuses Vite’s existing transform pipeline instead of running a separate Babel-based one, though actual gains vary by project size and configuration.



Did you enjoy this article?