简介
Vitest 是一个由 Vite 驱动的单元测试框架,专为现代前端项目设计。它提供了极快的测试执行速度、原生 ESM 支持、TypeScript 开箱即用等特性。
主要特性
- ⚡️ 极快的测试执行速度
- 🔧 与 Vite 配置完全兼容
- 📦 原生 ESM 支持
- 🎯 TypeScript 开箱即用
- 🖥️ 美观的 UI 界面
- 🧪 丰富的测试 API
安装
使用 npm
npm install -D vitest
使用 yarn
yarn add -D vitest
使用 pnpm
pnpm add -D vitest
基本配置
package.json 配置
{
"scripts": {
"test": "vitest",
"test:ui": "vitest --ui",
"test:run": "vitest run",
"coverage": "vitest run --coverage"
}
}
vitest.config.ts 配置
import { defineConfig } from "vitest/config";
export default defineConfig({
test: {
globals: true,
environment: "jsdom",
setupFiles: ["./src/test/setup.ts"],
},
});
编写测试
基本测试结构
import { describe, it, expect } from "vitest";
describe("数学运算", () => {
it("应该正确相加两个数字", () => {
expect(1 + 2).toBe(3);
});
it("应该正确处理负数", () => {
expect(-1 + 1).toBe(0);
});
});
测试生命周期钩子
import {
describe,
it,
beforeAll,
afterAll,
beforeEach,
afterEach,
} from "vitest";
describe("用户管理", () => {
beforeAll(() => {
// 在所有测试前执行一次
console.log("开始用户管理测试");
});
beforeEach(() => {
// 在每个测试前执行
// 设置测试数据
});
afterEach(() => {
// 在每个测试后执行
// 清理测试数据
});
afterAll(() => {
// 在所有测试后执行一次
console.log("用户管理测试完成");
});
it("应该创建新用户", () => {
// 测试逻辑
});
});
异步测试
import { describe, it, expect } from "vitest";
describe("异步操作", () => {
it("应该处理 Promise", async () => {
const result = await Promise.resolve("success");
expect(result).toBe("success");
});
it("应该处理回调函数", (done) => {
setTimeout(() => {
expect(true).toBe(true);
done();
}, 100);
});
});
测试运行器
命令行选项
# 运行所有测试
vitest
# 运行测试并监听文件变化
vitest --watch
# 运行特定测试文件
vitest src/components/Button.test.ts
# 运行匹配模式的测试
vitest --run -t "用户"
# 并行运行测试
vitest --threads
测试分组和过滤
describe.skip("跳过的测试组", () => {
it("这个测试不会运行", () => {
expect(true).toBe(false);
});
});
describe.only("只运行这个组", () => {
it("这个测试会运行", () => {
expect(true).toBe(true);
});
});
it.skip("跳过单个测试", () => {
expect(true).toBe(false);
});
it.only("只运行这个测试", () => {
expect(true).toBe(true);
});
模拟和存根
函数模拟
import { describe, it, expect, vi } from "vitest";
describe("函数模拟", () => {
it("应该模拟函数调用", () => {
const mockFn = vi.fn();
mockFn("hello");
expect(mockFn).toHaveBeenCalled();
expect(mockFn).toHaveBeenCalledWith("hello");
expect(mockFn).toHaveBeenCalledTimes(1);
});
it("应该模拟函数返回值", () => {
const mockFn = vi.fn().mockReturnValue("mocked");
expect(mockFn()).toBe("mocked");
});
});
模块模拟
import { describe, it, expect, vi } from "vitest";
// 模拟整个模块
vi.mock("./utils", () => ({
add: vi.fn().mockReturnValue(10),
multiply: vi.fn().mockReturnValue(20),
}));
// 模拟部分模块
vi.mock("./api", async () => {
const actual = await vi.importActual("./api");
return {
...actual,
fetchUser: vi.fn().mockResolvedValue({ id: 1, name: "Test" }),
};
});
覆盖率
安装覆盖率工具
npm install -D @vitest/coverage-v8
配置覆盖率
// vitest.config.ts
export default defineConfig({
test: {
coverage: {
provider: "v8",
reporter: ["text", "json", "html"],
exclude: ["node_modules/", "src/test/", "**/*.d.ts"],
},
},
});
运行覆盖率测试
# 生成覆盖率报告
vitest run --coverage
# 检查覆盖率阈值
vitest run --coverage --coverage.threshold.lines=80
UI 界面
安装 UI 界面
npm install -D @vitest/ui
启动 UI 界面
vitest --ui
UI 界面提供:
- 实时测试结果
- 测试覆盖率可视化
- 测试执行时间分析
- 交互式调试
配置选项
常用配置
import { defineConfig } from "vitest/config";
export default defineConfig({
test: {
// 全局变量
globals: true,
// 测试环境
environment: "jsdom",
// 设置文件
setupFiles: ["./src/test/setup.ts"],
// 包含的文件
include: ["src/**/*.{test,spec}.{js,mjs,cjs,ts,mts,cts,jsx,tsx}"],
// 排除的文件
exclude: ["node_modules", "dist", ".idea", ".git", ".cache"],
// 超时时间
testTimeout: 5000,
// 钩子超时时间
hookTimeout: 10000,
// 并行运行
threads: true,
// 最大并发数
maxConcurrency: 5,
},
});
最佳实践
测试文件命名
- 使用
.test.ts
或.spec.ts
后缀 - 保持与源文件相同的目录结构
测试数据管理
// 使用工厂函数创建测试数据
const createUser = (overrides = {}) => ({
id: 1,
name: "Test User",
email: "test@example.com",
...overrides,
});
it("应该显示用户信息", () => {
const user = createUser({ name: "John" });
// 测试逻辑
});
清理和重置
import { describe, it, beforeEach, afterEach, vi } from "vitest";
describe("API 测试", () => {
beforeEach(() => {
// 设置测试环境
});
afterEach(() => {
// 清理模拟
vi.clearAllMocks();
vi.resetAllMocks();
});
});
性能优化
- 使用
vi.isolateModules()
隔离模块 - 合理使用
beforeAll
和afterAll
- 避免在测试中创建不必要的对象
原文链接:https://code.ifrontend.net/archives/1044,转载请注明出处。
评论0