DEV Community

Alex Spinov
Alex Spinov

Posted on

Vitest Has a Free API — The Blazing Fast Unit Testing Framework for Vite

Vitest is a unit testing framework powered by Vite. It's compatible with Jest's API but 10-20x faster, with native ESM, TypeScript, and JSX support out of the box.

Why Vitest?

  • Vite-powered — uses Vite's transform pipeline, instant HMR for tests
  • Jest-compatible — same API, easy migration
  • TypeScript native — no ts-jest or babel config
  • In-source testing — write tests next to your code

Quick Start

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

Writing Tests

// math.test.ts
import { describe, it, expect, vi } from 'vitest';

describe('math', () => {
  it('adds numbers', () => {
    expect(1 + 2).toBe(3);
  });

  it('handles arrays', () => {
    expect([1, 2, 3]).toHaveLength(3);
    expect([1, 2, 3]).toContain(2);
  });

  it('handles objects', () => {
    expect({ a: 1, b: 2 }).toMatchObject({ a: 1 });
    expect({ a: 1 }).toHaveProperty('a', 1);
  });
});
Enter fullscreen mode Exit fullscreen mode

Mocking

import { vi } from 'vitest';

// Mock function
const fn = vi.fn();
fn('hello');
expect(fn).toHaveBeenCalledWith('hello');

// Mock module
vi.mock('./database', () => ({
  getUser: vi.fn().mockResolvedValue({ id: 1, name: 'Alice' }),
}));

// Spy
const spy = vi.spyOn(console, 'log');
console.log('test');
expect(spy).toHaveBeenCalledWith('test');
Enter fullscreen mode Exit fullscreen mode

Async Testing

it('fetches user', async () => {
  const user = await getUser(1);
  expect(user.name).toBe('Alice');
});

it('rejects on not found', async () => {
  await expect(getUser(999)).rejects.toThrow('Not found');
});
Enter fullscreen mode Exit fullscreen mode

Snapshot Testing

it('renders component', () => {
  const result = render(<Button>Click me</Button>);
  expect(result).toMatchSnapshot();
});

// Inline snapshots
it('formats date', () => {
  expect(formatDate(new Date('2024-01-01'))).toMatchInlineSnapshot('"Jan 1, 2024"');
});
Enter fullscreen mode Exit fullscreen mode

Configuration

// vitest.config.ts
import { defineConfig } from 'vitest/config';

export default defineConfig({
  test: {
    globals: true,
    environment: 'jsdom',
    coverage: {
      provider: 'v8',
      reporter: ['text', 'html'],
    },
    setupFiles: ['./test/setup.ts'],
  },
});
Enter fullscreen mode Exit fullscreen mode

Coverage

npx vitest run --coverage
Enter fullscreen mode Exit fullscreen mode

Testing your scraping code? Check out my Apify actors for production-tested scrapers, or email spinov001@gmail.com for custom solutions.

Vitest, Jest, or Bun test — which do you use? Share below!

Top comments (0)