DEV Community

Alex Spinov
Alex Spinov

Posted on

Vitest Has a Free Test Runner: Jest-Compatible Tests That Run 10x Faster With Native ESM and TypeScript

Jest needs ts-jest for TypeScript, @swc/jest for speed, babel-jest for ESM, and still doesn't support import.meta. Your test suite takes 45 seconds because Jest transforms every file through Babel.

What if your test runner was built on Vite — instant TypeScript, native ESM, and watch mode that reruns in milliseconds?

That's Vitest.

Quick Start

npm install -D vitest
Enter fullscreen mode Exit fullscreen mode
// package.json
{ "scripts": { "test": "vitest" } }
Enter fullscreen mode Exit fullscreen mode

That's the entire setup. No config file needed for most projects.

Jest-Compatible API

import { describe, it, expect, vi, beforeEach } from "vitest";

describe("UserService", () => {
  beforeEach(() => {
    vi.clearAllMocks();
  });

  it("creates a user with valid data", async () => {
    const user = await createUser({ name: "Aleksej", email: "dev@test.com" });

    expect(user).toMatchObject({
      name: "Aleksej",
      email: "dev@test.com",
    });
    expect(user.id).toBeDefined();
  });

  it("throws on duplicate email", async () => {
    await createUser({ name: "First", email: "same@test.com" });

    await expect(
      createUser({ name: "Second", email: "same@test.com" })
    ).rejects.toThrow("Email already exists");
  });
});
Enter fullscreen mode Exit fullscreen mode

Looks like Jest. Runs like Vite. Most Jest tests work in Vitest with minimal changes.

Speed Comparison

Operation Jest Vitest
Cold start (500 tests) 12s 1.8s
Watch mode rerun 3.2s 0.15s
TypeScript tests Needs ts-jest Native
ESM imports Experimental Native

Features Jest Doesn't Have

In-Source Testing

// utils.ts — tests live WITH the code
export function slugify(text: string): string {
  return text.toLowerCase().replace(/\s+/g, "-").replace(/[^a-z0-9-]/g, "");
}

if (import.meta.vitest) {
  const { describe, it, expect } = import.meta.vitest;

  describe("slugify", () => {
    it("converts spaces to hyphens", () => {
      expect(slugify("Hello World")).toBe("hello-world");
    });
    it("removes special characters", () => {
      expect(slugify("Hello World!@#")).toBe("hello-world");
    });
  });
}
Enter fullscreen mode Exit fullscreen mode

Tests are tree-shaken from production builds. They only run during vitest.

Type Testing

import { expectTypeOf, test } from "vitest";

test("function return types", () => {
  expectTypeOf(getUser).returns.toMatchTypeOf<Promise<User>>();
  expectTypeOf(getUser).parameter(0).toMatchTypeOf<string>();
});
Enter fullscreen mode Exit fullscreen mode

Browser Mode

// vitest.config.ts
export default defineConfig({
  test: {
    browser: {
      enabled: true,
      name: "chromium",
      provider: "playwright",
    },
  },
});
Enter fullscreen mode Exit fullscreen mode

Run tests in a real browser — DOM APIs, localStorage, Web Workers all work natively.

Mocking

import { vi } from "vitest";

// Mock modules
vi.mock("./database", () => ({
  db: {
    users: {
      findMany: vi.fn().mockResolvedValue([{ id: "1", name: "Test" }]),
      create: vi.fn().mockImplementation((data) => ({ id: "2", ...data })),
    },
  },
}));

// Mock timers
vi.useFakeTimers();
vi.advanceTimersByTime(1000);

// Spy on functions
const spy = vi.spyOn(console, "log");
myFunction();
expect(spy).toHaveBeenCalledWith("expected output");
Enter fullscreen mode Exit fullscreen mode

Coverage

vitest --coverage
Enter fullscreen mode Exit fullscreen mode

Built-in coverage with v8 or istanbul — no extra packages needed.

Migration From Jest

Most changes are mechanical:

Jest Vitest
jest.fn() vi.fn()
jest.mock() vi.mock()
jest.spyOn() vi.spyOn()
jest.config.js vitest.config.ts
@jest/globals vitest

When to Choose Vitest

Choose Vitest when:

  • You use Vite for your project (shared config)
  • TypeScript tests without extra setup
  • Watch mode speed matters (instant feedback)
  • You want ESM support without hacks

Stick with Jest when:

  • Large existing Jest test suite (migration cost)
  • You need Jest's mature snapshot testing ecosystem
  • Your project uses webpack (Vitest is Vite-based)

The Bottom Line

Vitest is Jest rebuilt for the Vite era. Same familiar API, 10x faster execution, native TypeScript and ESM. If you're starting a new project, there's little reason to choose Jest.

Start here: vitest.dev


Need custom data extraction, scraping, or automation? I build tools that collect and process data at scale — 78 actors on Apify Store and 265+ open-source repos. Email me: Spinov001@gmail.com | My Apify Actors

Top comments (0)