vitest
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseVitest
Vitest
Next generation testing framework powered by Vite.
由Vite驱动的下一代测试框架。
Quick Navigation
快速导航
- Test API - test, describe, hooks
- Expect API - matchers and assertions
- Mocking - vi.fn, vi.mock, fake timers
- Configuration - vitest.config.ts options
- CLI - command line reference
- Browser Mode - real browser testing
- 测试API - test、describe、钩子函数
- 断言API - 匹配器与断言
- 模拟功能 - vi.fn、vi.mock、假计时器
- 配置 - vitest.config.ts配置选项
- 命令行界面 - 命令行参考
- 浏览器模式 - 真实浏览器测试
When to Use
适用场景
- Testing Vite-based applications (shared config)
- Need Jest-compatible API with native ESM support
- Component testing in real browser
- Fast watch mode with HMR
- TypeScript testing without extra config
- Parallel test execution
- 测试基于Vite的应用(共享配置)
- 需要兼容Jest且支持原生ESM的API
- 真实浏览器中的组件测试
- 带有HMR的快速监听模式
- 无需额外配置的TypeScript测试
- 并行测试执行
Installation
安装
bash
npm install -D vitestRequirements: Vite >=v6.0.0, Node >=v20.0.0
bash
npm install -D vitest要求: Vite >=v6.0.0,Node >=v20.0.0
Quick Start
快速开始
js
// sum.js
export function sum(a, b) {
return a + b;
}js
// sum.test.js
import { expect, test } from "vitest";
import { sum } from "./sum.js";
test("adds 1 + 2 to equal 3", () => {
expect(sum(1, 2)).toBe(3);
});json
// package.json
{
"scripts": {
"test": "vitest",
"test:run": "vitest run",
"coverage": "vitest run --coverage"
}
}js
// sum.js
export function sum(a, b) {
return a + b;
}js
// sum.test.js
import { expect, test } from "vitest";
import { sum } from "./sum.js";
test("adds 1 + 2 to equal 3", () => {
expect(sum(1, 2)).toBe(3);
});json
// package.json
{
"scripts": {
"test": "vitest",
"test:run": "vitest run",
"coverage": "vitest run --coverage"
}
}Configuration
配置
ts
// vitest.config.ts (recommended)
import { defineConfig } from "vitest/config";
export default defineConfig({
test: {
globals: true, // Enable global test APIs
environment: "jsdom", // Browser-like environment
include: ["**/*.{test,spec}.{js,ts,jsx,tsx}"],
coverage: {
provider: "v8",
reporter: ["text", "html"],
},
},
});Or extend Vite config:
ts
// vite.config.ts
/// <reference types="vitest/config" />
import { defineConfig } from "vite";
export default defineConfig({
test: {
// test options
},
});ts
// vitest.config.ts (推荐)
import { defineConfig } from "vitest/config";
export default defineConfig({
test: {
globals: true, // 启用全局测试API
environment: "jsdom", // 类浏览器环境
include: ["**/*.{test,spec}.{js,ts,jsx,tsx}"],
coverage: {
provider: "v8",
reporter: ["text", "html"],
},
},
});或者扩展Vite配置:
ts
// vite.config.ts
/// <reference types="vitest/config" />
import { defineConfig } from "vite";
export default defineConfig({
test: {
// 测试选项
},
});Test File Naming
测试文件命名
By default, tests must contain or in filename:
.test..spec.sum.test.jssum.spec.ts__tests__/sum.js
默认情况下,测试文件名中必须包含或:
.test..spec.sum.test.jssum.spec.ts__tests__/sum.js
Key Commands
常用命令
bash
undefinedbash
undefinedWatch mode (default)
监听模式(默认)
vitest
vitest
Single run
单次运行
vitest run
vitest run
With coverage
生成覆盖率报告
vitest run --coverage
vitest run --coverage
Filter by file/test name
按文件/测试名称过滤
vitest sum
vitest -t "should add"
vitest sum
vitest -t "should add"
UI mode
UI模式
vitest --ui
vitest --ui
Browser tests
浏览器测试
vitest --browser.enabled
undefinedvitest --browser.enabled
undefinedCommon Patterns
常见模式
Basic Test
基础测试
ts
import { describe, it, expect, beforeEach } from "vitest";
describe("Calculator", () => {
let calc: Calculator;
beforeEach(() => {
calc = new Calculator();
});
it("adds numbers", () => {
expect(calc.add(1, 2)).toBe(3);
});
it("throws on invalid input", () => {
expect(() => calc.add("a", 1)).toThrow();
});
});ts
import { describe, it, expect, beforeEach } from "vitest";
describe("Calculator", () => {
let calc: Calculator;
beforeEach(() => {
calc = new Calculator();
});
it("adds numbers", () => {
expect(calc.add(1, 2)).toBe(3);
});
it("throws on invalid input", () => {
expect(() => calc.add("a", 1)).toThrow();
});
});Mocking
模拟功能
ts
import { vi, expect, test } from "vitest";
import { fetchUser } from "./api";
vi.mock("./api", () => ({
fetchUser: vi.fn(),
}));
test("uses mocked API", async () => {
vi.mocked(fetchUser).mockResolvedValue({ name: "John" });
const user = await fetchUser(1);
expect(fetchUser).toHaveBeenCalledWith(1);
expect(user.name).toBe("John");
});ts
import { vi, expect, test } from "vitest";
import { fetchUser } from "./api";
vi.mock("./api", () => ({
fetchUser: vi.fn(),
}));
test("uses mocked API", async () => {
vi.mocked(fetchUser).mockResolvedValue({ name: "John" });
const user = await fetchUser(1);
expect(fetchUser).toHaveBeenCalledWith(1);
expect(user.name).toBe("John");
});Snapshot Testing
快照测试
ts
import { expect, test } from "vitest";
test("matches snapshot", () => {
const result = generateConfig();
expect(result).toMatchSnapshot();
});
// Inline snapshot (auto-updates)
test("inline snapshot", () => {
expect({ foo: "bar" }).toMatchInlineSnapshot();
});ts
import { expect, test } from "vitest";
test("matches snapshot", () => {
const result = generateConfig();
expect(result).toMatchSnapshot();
});
// 内联快照(自动更新)
test("inline snapshot", () => {
expect({ foo: "bar" }).toMatchInlineSnapshot();
});Async Testing
异步测试
ts
import { expect, test } from "vitest";
test("async/await", async () => {
const result = await fetchData();
expect(result).toBeDefined();
});
test("resolves", async () => {
await expect(Promise.resolve("ok")).resolves.toBe("ok");
});
test("rejects", async () => {
await expect(Promise.reject(new Error())).rejects.toThrow();
});ts
import { expect, test } from "vitest";
test("async/await", async () => {
const result = await fetchData();
expect(result).toBeDefined();
});
test("resolves", async () => {
await expect(Promise.resolve("ok")).resolves.toBe("ok");
});
test("rejects", async () => {
await expect(Promise.reject(new Error())).rejects.toThrow();
});Fake Timers
假计时器
ts
import { vi, expect, test, beforeEach, afterEach } from "vitest";
beforeEach(() => {
vi.useFakeTimers();
});
afterEach(() => {
vi.useRealTimers();
});
test("advances time", () => {
const callback = vi.fn();
setTimeout(callback, 1000);
vi.advanceTimersByTime(1000);
expect(callback).toHaveBeenCalled();
});ts
import { vi, expect, test, beforeEach, afterEach } from "vitest";
beforeEach(() => {
vi.useFakeTimers();
});
afterEach(() => {
vi.useRealTimers();
});
test("advances time", () => {
const callback = vi.fn();
setTimeout(callback, 1000);
vi.advanceTimersByTime(1000);
expect(callback).toHaveBeenCalled();
});Jest Migration
Jest迁移
Most Jest code works with minimal changes:
diff
- import { jest } from '@jest/globals'
+ import { vi } from 'vitest'
- jest.fn()
+ vi.fn()
- jest.mock('./module')
+ vi.mock('./module')
- jest.useFakeTimers()
+ vi.useFakeTimers()Key differences:
- Use instead of
vijest - Globals not enabled by default (add )
globals: true - is hoisted (use
vi.mockfor non-hoisted)vi.doMock - No (use
jest.requireActual)vi.importActual
大多数Jest代码只需少量修改即可运行:
diff
- import { jest } from '@jest/globals'
+ import { vi } from 'vitest'
- jest.fn()
+ vi.fn()
- jest.mock('./module')
+ vi.mock('./module')
- jest.useFakeTimers()
+ vi.useFakeTimers()主要差异:
- 使用替代
vijest - 默认未启用全局变量(需添加)
globals: true - 会被提升(非提升场景使用
vi.mock)vi.doMock - 没有(使用
jest.requireActual替代)vi.importActual
Environment Selection
环境选择
ts
// vitest.config.ts
{
test: {
environment: 'jsdom', // or 'happy-dom', 'node', 'edge-runtime'
}
}
// Per-file (docblock at top)
/** @vitest-environment jsdom */ts
// vitest.config.ts
{
test: {
environment: 'jsdom', // 或'happy-dom'、'node'、'edge-runtime'
}
}
// 单文件配置(顶部文档块)
/** @vitest-environment jsdom */TypeScript
TypeScript
json
// tsconfig.json
{
"compilerOptions": {
"types": ["vitest/globals"]
}
}json
// tsconfig.json
{
"compilerOptions": {
"types": ["vitest/globals"]
}
}References
参考资料
See directory for detailed documentation on:
references/- Test API and hooks
- All expect matchers
- Mocking functions and modules
- Configuration options
- CLI commands
- Browser mode testing
请查看目录获取以下内容的详细文档:
references/- 测试API与钩子
- 所有断言匹配器
- 函数与模块模拟
- 配置选项
- CLI命令
- 浏览器模式测试