Vitest testing framework. Covers unit tests, mocking, and coverage. Use for testing Vite-based and Node.js projects. USE WHEN: user mentions "vitest", "vite test", "unit test", asks about "vi.fn", "vi.mock", "test coverage", "mock functions", "test vite project" DO NOT USE FOR: E2E tests - use `playwright` instead; React component testing - combine with `testing-library`; Jest projects - use `jest` instead

GitHub
Install command
npx skhub add claude-dev-suite/vitest
Markdown
SKILL.md

Vitest Core Knowledge

Deep Knowledge: Use mcp__documentation__fetch_docs with technology: vitest for comprehensive documentation.

When NOT to Use This Skill

  • E2E Testing - Use playwright or cypress for browser-based end-to-end tests
  • React Component Testing - Combine this skill with testing-library for component tests
  • Jest Migration - If project uses Jest, use jest skill instead (syntax is similar but not identical)
  • API Integration Tests - Use framework-specific integration test skills (spring-boot-integration, etc.)

Basic Test

import { describe, it, expect, beforeEach, vi } from 'vitest';
import { calculateTotal } from './utils';

describe('calculateTotal', () => {
  it('should sum array of numbers', () => {
    expect(calculateTotal([1, 2, 3])).toBe(6);
  });

  it('should return 0 for empty array', () => {
    expect(calculateTotal([])).toBe(0);
  });
});

Matchers

// Equality
expect(value).toBe(exact);
expect(value).toEqual(deepEqual);
expect(value).toMatchObject(partial);

// Truthiness
expect(value).toBeTruthy();
expect(value).toBeFalsy();
expect(value).toBeNull();
expect(value).toBeDefined();

// Numbers
expect(value).toBeGreaterThan(n);
expect(value).toBeCloseTo(0.3, 5);

// Strings
expect(str).toMatch(/pattern/);
expect(str).toContain('substring');

// Arrays
expect(arr).toContain(item);
expect(arr).toHaveLength(3);

// Errors
expect(() => fn()).toThrow();
expect(() => fn()).toThrowError('message');

Mocking

// Mock function
const mockFn = vi.fn();
mockFn.mockReturnValue(42);
mockFn.mockResolvedValue({ data: [] });

// Mock module
vi.mock('./api', () => ({
  fetchUsers: vi.fn().mockResolvedValue([])
}));

// Spy
const spy = vi.spyOn(object, 'method');
expect(spy).toHaveBeenCalledWith('arg');

// Reset
vi.clearAllMocks();
vi.resetAllMocks();

Async Tests

it('should fetch data', async () => {
  const data = await fetchUsers();
  expect(data).toHaveLength(3);
});

it('should reject', async () => {
  await expect(fetchFail()).rejects.toThrow('Error');
});

Config

// vitest.config.ts
export default defineConfig({
  test: {
    globals: true,
    environment: 'jsdom',
    coverage: { provider: 'v8', reporter: ['text', 'html'] }
  }
});

Production Readiness

Test Organization

// Proper test structure
describe('UserService', () => {
  // Setup/teardown at appropriate level
  let service: UserService;
  let mockDb: MockedObject<Database>;

  beforeAll(async () => {
    // Expensive setup once
    await setupTestDatabase();
  });

  beforeEach(() => {
    // Reset state before each test
    mockDb = vi.mocked(new Database());
    service = new UserService(mockDb);
    vi.clearAllMocks();
  });

  afterAll(async () => {
    // Cleanup
    await teardownTestDatabase();
  });

  describe('create', () => {
    it('should create user with valid data', async () => {
      // Arrange
      const input = { name: 'John', email: 'john@example.com' };
      mockDb.insert.mockResolvedValue({ id: '1', ...input });

      // Act
      const result = await service.create(input);

      // Assert
      expect(result).toMatchObject(input);
      expect(mockDb.insert).toHaveBeenCalledWith('users', input);
    });

    it('should throw on duplicate email', async () => {
      mockDb.insert.mockRejectedValue(new UniqueConstraintError());
      await expect(service.create(input)).rejects.toThrow('Email already exists');
    });
  });
});

Coverage Configuration

// vitest.config.ts
export default defineConfig({
  test: {
    coverage: {
      provider: 'v8',
      reporter: ['text', 'html', 'lcov'],
      exclude: [
        'node_modules/',
        'test/',
        '**/*.d.ts',
        '**/*.config.*',
        '**/types/**',
      ],
      thresholds: {
        lines: 80,
        functions: 80,
        branches: 75,
        statements: 80,
      },
    },
  },
});

CI Configuration

# GitHub Actions
- name: Run tests
  run: npm run test:ci

- name: Upload coverage
  uses: codecov/codecov-action@v3
  with:
    files: ./coverage/lcov.info
    fail_ci_if_error: true
// package.json scripts
{
  "scripts": {
    "test": "vitest",
    "test:ci": "vitest run --coverage --reporter=junit --outputFile=test-results.xml",
    "test:watch": "vitest --watch"
  }
}

Monitoring Metrics

MetricTarget
Line coverage> 80%
Branch coverage> 75%
Test execution time< 60s
Flaky test rate0%

Checklist

  • Arrange-Act-Assert pattern
  • Isolated tests (no shared state)
  • Meaningful test descriptions
  • Coverage thresholds enforced
  • CI/CD integration
  • No console.log in tests
  • Mocks reset between tests
  • Async tests properly awaited
  • Edge cases covered
  • Error paths tested

Anti-Patterns

Anti-PatternWhy It's BadSolution
Testing implementation detailsTests break on refactorTest behavior, not internals
Sharing state between testsFlaky, order-dependent testsUse beforeEach, isolated setup
Arbitrary waits (setTimeout)Slow, unreliable testsUse waitFor or async utilities
Not resetting mocksPrevious test affects nextvi.clearAllMocks() in beforeEach
Testing private methodsTight coupling to implementationTest through public API
One giant testHard to debug failuresOne assertion per test (ideally)
No error case testsProduction bugs slip throughTest happy path AND error paths

Quick Troubleshooting

ProblemLikely CauseSolution
"Cannot find module"Missing mock setupCheck vi.mock() path matches import
Test timeoutAsync not awaitedEnsure all async operations use await
"Expected 0 calls, received 1"Mock not clearedAdd vi.clearAllMocks() in beforeEach
Flaky testsShared state or timingIsolate setup, avoid setTimeout
Coverage not updatingCache issueRun with --no-cache flag
"TypeError: vi.fn is not a function"Missing importImport { vi } from 'vitest'

Reference Documentation

Discovery
Tags

No tags published for this skill.

Version
Latest version metadata

Version

v2026.09.24

Published

Sep 24, 2026

Category

Uncategorized

License

MIT

Source path

skills/testing/vitest

Default branch

main

Latest commit

9496306

Tree SHA

fe4e2f1