All skills
antfu avatar

/vitest

@d02c484 official
by Anthony Fuantfu/skills5.9k stars
335

Vitest fast unit testing framework powered by Vite with Jest-compatible API. Use when writing tests, mocking, configuring coverage, or working with test filtering and fixtures.

Use this Skill: https://skilld.dev/gh/antfu/skills/vitest

This session only. Nothing lands on disk.

referencescore-hooks.md

≈1.2k tokens on demand. Your agent reads this file only when SKILL.md points to it.

Lifecycle Hooks

Basic Hooks

import { afterAll, afterEach, beforeAll, beforeEach, test } from 'vitest'

beforeAll(async () => {
  // Runs once before all tests in file/suite
  await setupDatabase()
})

afterAll(async () => {
  // Runs once after all tests in file/suite
  await teardownDatabase()
})

beforeEach(async () => {
  // Runs before each test
  await clearTestData()
})

afterEach(async () => {
  // Runs after each test
  await cleanupMocks()
})

Cleanup Return Pattern

Return cleanup function from before* hooks:

beforeAll(async () => {
  const server = await startServer()
  
  // Returned function runs as afterAll
  return async () => {
    await server.close()
  }
})

beforeEach(async () => {
  const connection = await connect()
  
  // Runs as afterEach
  return () => connection.close()
})

Scoped Hooks

Hooks apply to current suite and nested suites:

describe('outer', () => {
  beforeEach(() => console.log('outer before'))
  
  test('test 1', () => {}) // outer before → test
  
  describe('inner', () => {
    beforeEach(() => console.log('inner before'))
    
    test('test 2', () => {}) // outer before → inner before → test
  })
})

Hook Timeout

beforeAll(async () => {
  await slowSetup()
}, 30_000) // 30 second timeout

Around Hooks

Wrap tests with setup/teardown context:

import { aroundEach, test } from 'vitest'

// Wrap each test in database transaction
aroundEach(async (runTest) => {
  await db.beginTransaction()
  await runTest() // Must be called!
  await db.rollback()
})

test('insert user', async () => {
  await db.insert({ name: 'Alice' })
  // Automatically rolled back after test
})

aroundAll

Wrap entire suite:

import { aroundAll, test } from 'vitest'

aroundAll(async (runSuite) => {
  console.log('before all tests')
  await runSuite() // Must be called!
  console.log('after all tests')
})

Multiple Around Hooks

Nested like onion layers:

aroundEach(async (runTest) => {
  console.log('outer before')
  await runTest()
  console.log('outer after')
})

aroundEach(async (runTest) => {
  console.log('inner before')
  await runTest()
  console.log('inner after')
})

// Order: outer before → inner before → test → inner after → outer after

Test Hooks

Inside test body:

import { onTestFailed, onTestFinished, test } from 'vitest'

test('with cleanup', () => {
  const db = connect()
  
  // Runs after test finishes (pass or fail)
  onTestFinished(() => db.close())
  
  // Only runs if test fails
  onTestFailed(({ task }) => {
    console.log('Failed:', task.result?.errors)
  })
  
  db.query('SELECT * FROM users')
})

Reusable Cleanup Pattern

function useTestDb() {
  const db = connect()
  onTestFinished(() => db.close())
  return db
}

test('query users', () => {
  const db = useTestDb()
  expect(db.query('SELECT * FROM users')).toBeDefined()
})

test('query orders', () => {
  const db = useTestDb() // Fresh connection, auto-closed
  expect(db.query('SELECT * FROM orders')).toBeDefined()
})

Concurrent Test Hooks

For concurrent tests, use context's hooks:

test.concurrent('concurrent', ({ onTestFinished }) => {
  const resource = allocate()
  onTestFinished(() => resource.release())
})

Extended Test Hooks

With test.extend, hooks are type-aware and must be called on the extended test:

const test = base
  .extend('db', { scope: 'file' }, async ({}, { onCleanup }) => {
    const db = await createDb()
    onCleanup(() => db.close())
    return db
  })

// Test-level hooks see fixtures
test.beforeEach(({ db }) => db.seed())
test.afterEach(({ db }) => db.clear())

// Suite-level hooks (4.1+) can access file/worker-scoped fixtures
test.beforeAll(({ db }) => db.createUsers())
test.aroundAll(async (runSuite, { db }) => db.transaction(runSuite))

Suite-level hooks (beforeAll/afterAll/aroundAll) only see file/worker-scoped fixtures, and the global beforeAll/afterAll cannot access custom fixtures — use test.beforeAll etc.

Hook Execution Order

Default order (stack):

  1. beforeAll (in order)
  2. beforeEach (in order)
  3. Test
  4. afterEach (reverse order)
  5. afterAll (reverse order)

Configure with sequence.hooks:

defineConfig({
  test: {
    sequence: {
      hooks: 'list', // 'stack' (default), 'list', 'parallel'
    },
  },
})

Key Points

  • Hooks are not called during type checking
  • Return cleanup function from before* to avoid after* duplication
  • aroundEach/aroundAll must call runTest()/runSuite()
  • onTestFinished always runs, even if test fails
  • Use context hooks for concurrent tests
<!-- Source references: - https://vitest.dev/api/hooks.html -->

Source: SKILL.md on GitHub

No alerts3d5 checks · Risk SAFE
  • Gen Agent Trust Hub3d

    The skill provides comprehensive documentation and reference material for the Vitest testing framework. It covers configuration, CLI usage, mocking, coverage, and advanced features like type testing and benchmarking. No security issues were detected; the instructions follow standard development and testing practices.

  • Socket3d

    No alerts

  • Snyk3d

    Risk: LOW · No issues

  • Runlayer7mo

    1/18 files flagged

  • ZeroLeaks5mo

    Score: 93/100 · 2 sections analyzed

Signed by skilld at d02c484. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub 2 days ago.

Activeupdated 4 days ago
Other metadata
metadata
{
  "author": "Anthony Fu",
  "version": "2026.9.25",
  "source": "Generated from https://github.com/vitest-dev/vitest, scripts located at https://github.com/antfu/skills"
}

README badge

README badge for antfu/skills/vitest

Vitest is a Jest-compatible unit testing framework powered by Vite, with native ESM, TypeScript, and JSX support. Use it for writing tests with smart watch mode, mocking, fixtures, coverage reporting, and snapshot testing in projects already using Vite.

Generated from the current SKILL.md.

Is Vitest a drop-in replacement for Jest?
Mostly. Vitest provides a Jest-compatible API and can run most Jest test suites without modification, but it uses Vite's transformation pipeline instead of Jest's, so some edge cases may differ.
Does Vitest require configuration?
No. It natively supports ESM, TypeScript, and JSX out of the box and shares Vite's config, transformers, and resolvers, so many projects need minimal or no additional setup.
What coverage providers does Vitest support?
Vitest includes built-in coverage via V8 or Istanbul providers.
Can I run tests in parallel?
Yes. Vitest uses multi-threaded workers for parallel test execution and supports sharding across multiple processes.
What test environments are available?
Vitest supports node, jsdom, happy-dom, and custom environments.

Generated from the current SKILL.md. These answers refresh after source changes.