Skip to content
Vitest 1
Main Navigation GuideAPIConfigAdvanced
1.6.1
0.34.6

English

简体中文
繁體中文
Español
Français
Русский
Português – Brasil
Deutsch
日本語
한국어
Italiano
Polski
Türkçe
čeština
magyar

English

简体中文
繁體中文
Español
Français
Русский
Português – Brasil
Deutsch
日本語
한국어
Italiano
Polski
Türkçe
čeština
magyar

Appearance

Sidebar Navigation

Guide

Why Vitest

Getting Started

Features

Workspace

CLI

Test Filtering

Reporters

Coverage

Snapshot

Mocking

Testing Types

Vitest UI

Browser Mode

In-source Testing

Test Context

Environment

Extending Matchers

IDE Integration

Debugging

Comparisons

Migration Guide

Common Errors

Improving Performance

API

Test API Reference

Mock Functions

Vi Utility

Expect

ExpectTypeOf

assert

assertType

Config

Config File

Config Reference

On this page

Test Context ​

Inspired by Playwright Fixtures, Vitest's test context allows you to define utils, states, and fixtures that can be used in your tests.

Usage ​

The first argument for each test callback is a test context.

ts
import { it } from 'vitest';

it('should work', ctx => {
  // prints name of the test
  console.log(ctx.task.name);
});

Built-in Test Context ​

context.task ​

A readonly object containing metadata about the test.

context.expect ​

The expect API bound to the current test:

ts
import { it } from 'vitest';

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

This API is useful for running snapshot tests concurrently because global expect cannot track them:

ts
import { it } from 'vitest';

it.concurrent('math is easy', ({ expect }) => {
  expect(2 + 2).toMatchInlineSnapshot();
});

it.concurrent('math is hard', ({ expect }) => {
  expect(2 * 2).toMatchInlineSnapshot();
});

context.skip ​

Skips subsequent test execution and marks test as skipped:

ts
import { expect, it } from 'vitest';

it('math is hard', ({ skip }) => {
  skip();
  expect(2 + 2).toBe(5);
});

Extend Test Context ​

Vitest provides two different ways to help you extend the test context.

test.extend ​

WARNING

This API is available since Vitest 0.32.3.

Like Playwright, you can use this method to define your own test API with custom fixtures and reuse it anywhere.

For example, we first create myTest with two fixtures, todos and archive.

ts
// my-test.ts
import { test } from 'vitest';

const todos = [];
const archive = [];

export const myTest = test.extend({
  todos: async ({ task }, use) => {
    // setup the fixture before each test function
    todos.push(1, 2, 3);

    // use the fixture value
    await use(todos);

    // cleanup the fixture after each test function
    todos.length = 0;
  },
  archive,
});

Then we can import and use it.

ts
import { expect } from 'vitest';
import { myTest } from './my-test.ts';

myTest('add items to todos', ({ todos }) => {
  expect(todos.length).toBe(3);

  todos.push(4);
  expect(todos.length).toBe(4);
});

myTest('move items from todos to archive', ({ todos, archive }) => {
  expect(todos.length).toBe(3);
  expect(archive.length).toBe(0);

  archive.push(todos.pop());
  expect(todos.length).toBe(2);
  expect(archive.length).toBe(1);
});

We can also add more fixtures or override existing fixtures by extending myTest.

ts
export const myTest2 = myTest.extend({
  settings: {
    // ...
  },
});

Fixture initialization ​

Vitest runner will smartly initialize your fixtures and inject them into the test context based on usage.

ts
import { test } from 'vitest';

async function todosFn({ task }, use) {
  await use([1, 2, 3]);
}

const myTest = test.extend({
  todos: todosFn,
  archive: [],
});

// todosFn will not run
myTest('', () => {});
myTest('', ({ archive }) => {});

// todosFn will run
myTest('', ({ todos }) => {});

WARNING

When using test.extend() with fixtures, you should always use the object destructuring pattern { todos } to access context both in fixture function and test function.

Automatic fixture ​

WARNING

This feature is available since Vitest 1.3.0.

Vitest also supports the tuple syntax for fixtures, allowing you to pass options for each fixture. For example, you can use it to explicitly initialize a fixture, even if it's not being used in tests.

ts
import { test as base } from 'vitest';

const test = base.extend({
  fixture: [
    async ({}, use) => {
      // this function will run
      setup();
      await use();
      teardown();
    },
    { auto: true }, // Mark as an automatic fixture
  ],
});

test('', () => {});

TypeScript ​

To provide fixture types for all your custom contexts, you can pass the fixtures type as a generic.

ts
interface MyFixtures {
  todos: number[];
  archive: number[];
}

const myTest = test.extend<MyFixtures>({
  todos: [],
  archive: [],
});

myTest('', context => {
  expectTypeOf(context.todos).toEqualTypeOf<number[]>();
  expectTypeOf(context.archive).toEqualTypeOf<number[]>();
});

beforeEach and afterEach ​

The contexts are different for each test. You can access and extend them within the beforeEach and afterEach hooks.

ts
import { beforeEach, it } from 'vitest';

beforeEach(async context => {
  // extend context
  context.foo = 'bar';
});

it('should work', ({ foo }) => {
  console.log(foo); // 'bar'
});

TypeScript ​

To provide property types for all your custom contexts, you can aggregate the TestContext type by adding

ts
declare module 'vitest' {
  export interface TestContext {
    foo?: string;
  }
}

If you want to provide property types only for specific beforeEach, afterEach, it and test hooks, you can pass the type as a generic.

ts
interface LocalTestContext {
  foo: string;
}

beforeEach<LocalTestContext>(async context => {
  // typeof context is 'TestContext & LocalTestContext'
  context.foo = 'bar';
});

it<LocalTestContext>('should work', ({ foo }) => {
  // typeof foo is 'string'
  console.log(foo); // 'bar'
});
Pager
Previous pageIn-source Testing
Next pageEnvironment

Released under the MIT License.

Copyright (c) 2021-Present Vitest Team

https://v1.vitest.dev/guide/test-context

Released under the MIT License.

Copyright (c) 2021-Present Vitest Team