All free skills / Other majors

vitest 5.x

Use Vitest ^5.0.0 standalone assertions and mock functions correctly, while avoiding APIs that require the Vitest runner and accounting for v5 migration changes.

For
vitest@5.0.0
Verified
2026-09-07, 5 examples executed
Skill package
@modootoday/pmcp-vitest@5.0.0

Use this skill for free

No PMCP login or subscription is required. Download the original instructions, or install the content-only archive with your project's package manager.

Download SKILL.md · Download package archive

npm install --save-dev https://pmcp.build/skills/vitest/5/package.tgz

PMCP discovers the installed package's instructions. Connect your runtime after installation.

Archive integritysha512-iSfnL92nXDk6nG6Ss8FgmGgr9mwf/gIYfZtfRppQcJIKZBdQXC0Ht5JMbaPEN5PHlF+yq75xUDKniDjJXqoNcw==

Complete instructions

Verified against vitest@5.0.0 on 2026-09-07. 5 of 5 examples executed.

Vitest ^5.0.0

Requirements

Vitest 5 requires Node.js >= 22.12.0 and Vite >= 6.4.0.

Assertions are bundled into vitest; import expect, vi, and test APIs from vitest rather than relying on @vitest/expect.

What can run in a plain script

A plain script can directly exercise assertions and several mock-function APIs exported by vitest. The examples below are standalone files: they do not use the Vitest runner.

Assertions

Use expect from vitest for matchers such as toBe, toBeCloseTo, and toContain.

import { expect } from 'vitest'

expect(Math.sqrt(4)).toBe(2)
expect(Math.sqrt(144)).toBe(12)
expect(Math.sqrt(0)).toBe(0)
expect(0.1 + 0.2).toBeCloseTo(0.3)
expect('vitest').toContain('test')

expect.assertions(count) is documented for checking the number of assertions made during a test run; it is not a standalone assertion-counting mechanism to rely on in an ordinary script.

Mock functions

vi.fn() creates a mock function. Calls are recorded even when the function has no implementation, in which case it returns undefined.

import { expect, vi } from 'vitest'

const getApples = vi.fn()

getApples()

expect(getApples).toHaveBeenCalled()
expect(getApples).toHaveBeenCalledTimes(1)
expect(getApples()).toBeUndefined()

Spying on an object method

vi.spyOn(object, key) creates a mock around an existing object method. Restore it with vi.restoreAllMocks() when the original implementation should be put back.

import { expect, vi } from 'vitest'

const calculator = {
  add(a: number, b: number) {
    return a + b
  },
}

const add = vi.spyOn(calculator, 'add')

expect(calculator.add(2, 3)).toBe(5)
expect(add).toHaveBeenCalledWith(2, 3)

vi.restoreAllMocks()
expect(calculator.add(1, 1)).toBe(2)

Conditional mock behavior with vi.when

Vitest 5 adds argument-based behavior configuration for mocks. Chain calledWith(...).thenReturn(...) clauses to return different values for different arguments.

import { expect, vi } from 'vitest'

const spy = vi.fn()

vi.when(spy)
  .calledWith(1)
  .thenReturn('one')
  .calledWith(2)
  .thenReturn('two')

expect(spy(1)).toBe('one')
expect(spy(2)).toBe('two')

Mock lifecycle APIs

  • vi.clearAllMocks() clears recorded calls while preserving mock implementations.
  • vi.resetAllMocks() resets mock state and restores the mock's initial implementation. For a mock created with an implementation, that initial implementation remains available.
  • vi.restoreAllMocks() restores spied-on originals.

Vitest 5 also defaults clearMocks to true, so the runner calls vi.clearAllMocks() before every test while preserving implementations.

import { expect, vi } from 'vitest'

const mock = vi.fn(() => 'value')

mock()
expect(mock).toHaveBeenCalledTimes(1)

vi.clearAllMocks()
expect(mock).toHaveBeenCalledTimes(0)
expect(mock()).toBe('value')

vi.resetAllMocks()
expect(mock()).toBe('value')

vi.mockObject(value) is not a standalone API in this environment: it reaches for Vitest's initialized mocker and throws when no runner has initialized it. Use it only under Vitest's transformed module runner.

APIs that require the Vitest runner

Importing test or it from vitest is not enough to execute tests in an ordinary script. The callback is collected and run by Vitest's runner or its CLI/build integration.

The documented form is:

import { expect, test } from 'vitest'

test('Math.sqrt works for perfect squares', () => {
  expect(Math.sqrt(4)).toBe(2)
})

Test callbacks can receive a test context. Documented built-ins include task, expect, signal, bench, onTestFailed, and onTestFinished:

import { it } from 'vitest'

it('math is easy', ({ expect }) => {
  expect(2 + 2).toBe(4)
})

These snippets belong in files executed by Vitest, not in a direct bun example.ts invocation.

v5 benchmarks

Benchmarks moved into regular tests through the bench test-context fixture. The old standalone shape is not the v5 shape:

import { test } from 'vitest'

test('sort', async ({ bench }) => {
  await bench('sort', () => {
    [3, 1, 2].sort()
  }).run()
})

bench.skip, bench.only, and bench.todo were removed. Use test.skip, test.only, and test.todo around the containing test instead. The bench fixture is runner-provided, so this is not a standalone Bun example.

Module mocking

vi.mock substitutes imported modules and works with import, not require. Vitest statically analyzes and hoists it, so calls must be at module top level in v5:

import { vi } from 'vitest'

vi.mock('./path/to/module.js', () => ({
  default: { myDefaultKey: vi.fn() },
  namedExport: vi.fn(),
}))

Module mocking depends on Vitest's transformed module runner and is intended for test files. It is not equivalent to ordinary standalone Node or Bun module behavior. Unlike vi.mock, vi.doMock and vi.doUnmock remain non-hoisted.

Do not put vi.mock, vi.unmock, or vi.hoisted inside a function or nested scope in v5; nested calls throw.

v5 migration traps

  • Replace removed test.sequential, describe.sequential, and sequential options with concurrent: false.
  • Do not use the former top-level bench(...) API for v5 benchmarks; use the test-context bench fixture.
  • Do not import removed entrypoints such as vitest/coverage, vitest/reporters, vitest/environments, vitest/snapshot, vitest/runners, vitest/suite, vitest/mocker, or vitest/internal/module-runner. The migration replacements include vitest/node, vitest/runtime, TestRunner from vitest, static TestRunner methods, and @vitest/mocker.

Not covered

This skill does not cover Vitest configuration, CLI invocation, runner/build integration, environment setup, reporters, coverage configuration, snapshots, the complete matcher catalog, custom matcher implementation, module-resolution details, vi.mockObject outside the runner, or the full test-context lifecycle API. Those areas require the Vitest runner or additional documentation beyond the supplied research.