Why Developers Are Switching From Jest to Vitest
Last year, a team I was consulting for spent 12 minutes waiting for their Jest test suite to finish. They had 2,000 tests across a Vite-based monorepo. After migrating to Vitest over a weekend, that same suite ran in under 2 minutes.
Vitest is a next-generation testing framework powered by Vite. It is blazing fast, Jest-compatible, and completely free.
What Makes Vitest Special
- Vite-powered — uses Vite dev server for instant test transforms
- Jest-compatible API — migrate with minimal changes
-
Native TypeScript support — no
ts-jestconfiguration - Watch mode by default — re-runs only affected tests
-
Built-in coverage — via
v8oristanbul, no extra packages - In-source testing — write tests right next to your code
- Workspace support — test monorepos with a single config
Getting Started
# Install Vitest
npm install -D vitest
# Add to package.json
# "scripts": { "test": "vitest" }
Create vitest.config.ts:
import { defineConfig } from "vitest/config";
export default defineConfig({
test: {
globals: true,
environment: "node",
coverage: {
provider: "v8",
reporter: ["text", "json", "html"],
},
},
});
Your First Test
// utils.ts
export function slugify(text: string): string {
return text
.toLowerCase()
.replace(/[^\w\s-]/g, "")
.replace(/[\s_]+/g, "-")
.replace(/^-+|-+$/g, "");
}
export function truncate(str: string, maxLength: number): string {
if (str.length <= maxLength) return str;
return str.slice(0, maxLength - 3) + "...";
}
// utils.test.ts
import { describe, it, expect } from "vitest";
import { slugify, truncate } from "./utils";
describe("slugify", () => {
it("converts text to URL-friendly slug", () => {
expect(slugify("Hello World")).toBe("hello-world");
expect(slugify("Vitest Is Awesome!")).toBe("vitest-is-awesome");
});
it("handles special characters", () => {
expect(slugify("price: $100")).toBe("price-100");
expect(slugify(" extra spaces ")).toBe("extra-spaces");
});
});
describe("truncate", () => {
it("returns full string if under max length", () => {
expect(truncate("short", 10)).toBe("short");
});
it("truncates with ellipsis", () => {
expect(truncate("This is a long string", 10)).toBe("This is...");
});
});
Run with:
npx vitest
Mocking Made Simple
Vitest has powerful mocking built in:
import { describe, it, expect, vi } from "vitest";
// Mock a module
vi.mock("./api", () => ({
fetchUser: vi.fn().mockResolvedValue({ id: 1, name: "Alice" }),
}));
import { fetchUser } from "./api";
import { getUserDisplay } from "./user-service";
describe("getUserDisplay", () => {
it("formats user data", async () => {
const result = await getUserDisplay(1);
expect(result).toBe("Alice (ID: 1)");
expect(fetchUser).toHaveBeenCalledWith(1);
});
});
Snapshot Testing
import { it, expect } from "vitest";
function generateConfig(env: string) {
return {
database: env === "prod" ? "postgres" : "sqlite",
cache: env === "prod" ? "redis" : "memory",
debug: env !== "prod",
};
}
it("generates correct config for production", () => {
expect(generateConfig("prod")).toMatchInlineSnapshot(`
{
"cache": "redis",
"database": "postgres",
"debug": false,
}
`);
});
In-Source Testing
One of Vitest unique features — write tests next to your code:
// math.ts
export function factorial(n: number): number {
if (n < 0) throw new Error("Negative numbers not supported");
if (n <= 1) return 1;
return n * factorial(n - 1);
}
// Tests are tree-shaken from production builds
if (import.meta.vitest) {
const { it, expect } = import.meta.vitest;
it("computes factorial", () => {
expect(factorial(0)).toBe(1);
expect(factorial(5)).toBe(120);
expect(factorial(10)).toBe(3628800);
});
it("throws on negative input", () => {
expect(() => factorial(-1)).toThrow();
});
}
Speed Comparison
| Framework | 1000 Tests | Watch Restart | Config Complexity |
|---|---|---|---|
| Jest | 8.2s | 3.1s | Medium |
| Mocha | 6.5s | 2.8s | High |
| Vitest | 1.4s | 0.3s | Low |
Migration From Jest
Most Jest tests work with Vitest by just changing imports:
- import { describe, it, expect, jest } from "@jest/globals";
+ import { describe, it, expect, vi } from "vitest";
- jest.fn()
+ vi.fn()
- jest.mock("./module")
+ vi.mock("./module")
The Bottom Line
Vitest is the testing framework that Jest should have been. It is faster, simpler to configure, and works natively with TypeScript and modern JavaScript tooling. If you are starting a new project or tired of slow Jest runs, give Vitest a try.
Start here: vitest.dev
💡 Need web scraping or data extraction? Check out my Apify actors or email me at spinov001@gmail.com for custom solutions!
Top comments (0)