Vitest 测试框架完全指南 – 极速单元测试解决方案

简介

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() 隔离模块
  • 合理使用 beforeAllafterAll
  • 避免在测试中创建不必要的对象

Vitest 测试框架完全指南 - 极速单元测试解决方案 - 高质量源码分享平台-免费下载各类网站源码与模板及前沿技术分享