单元测试完全指南:Jest、Vitest、Testing Library

深入单元测试核心原理与实战工具,掌握 Jest、Vitest、Testing Library,构建高质量前端测试体系。

作者
资源变现技术团队测试工程师

🧪 测试金字塔

测试金字塔是测试策略的经典模型。根据 Google 测试博客,理想比例是:70% 单元测试、20% 集成测试、10% E2E 测试。

E2E 测试(10%)
真实浏览器、完整流程
集成测试(20%)
API、组件交互
单元测试(70%)
函数、组件、模块
测试类型速度成本可靠性调试难度
单元测试快(毫秒)低高(隔离)易
集成测试中(秒级)中中中
E2E 测试慢(分钟级)高低(脆弱)难

💡 独特观点

单元测试的真正价值不是"发现错误",而是驱动设计。TDD(测试驱动开发)让你先想清楚接口,再写实现,产出更优质的代码。

🧪 单元测试核心

单元测试是最小可测试单元(函数、组件、模块)的验证。核心是 AAA 模式:Arrange(准备)、Act(执行)、Assert(断言)。

1. AAA 模式(Arrange-Act-Assert)

📝 AAA 模式示例(Jest)

// 测试函数:计算购物车总价
function calculateTotal(items) {
  return items.reduce((sum, item) => sum + item.price * item.quantity, 0);
}

// ✅ 好的单元测试(AAA 模式)
describe('calculateTotal', () => {
  test('应正确计算购物车总价', () => {
    // 1. Arrange(准备):创建测试数据
    const items = [
      { name: '商品A', price: 100, quantity: 2 },
      { name: '商品B', price: 50, quantity: 1 },
    ];

    // 2. Act(执行):调用被测函数
    const result = calculateTotal(items);

    // 3. Assert(断言):验证结果
    expect(result).toBe(250);  // 100*2 + 50*1 = 250
  });

  test('空购物车应返回 0', () => {
    // Arrange
    const items = [];

    // Act
    const result = calculateTotal(items);

    // Assert
    expect(result).toBe(0);
  });
});

2. 测试覆盖率(Coverage)

覆盖率指标:

语句覆盖率(Statement)

每行代码是否执行到

function abs(x) {
  if (x >= 0) {     // ① 需要测试 x >= 0
    return x;          // ② 需要测试 x >= 0
  } else {
    return -x;         // ③ 需要测试 x < 0
  }
}

分支覆盖率(Branch)

每个 if/else 分支是否覆盖

// 需要两个测试用例:
// 1. x >= 0 → 走 if 分支
// 2. x < 0 → 走 else 分支

函数覆盖率(Function)

每个函数是否调用到

行覆盖率(Line)

每一行是否执行(类似语句覆盖)

📝 生成覆盖率报告(Jest)

// jest.config.js
module.exports = {
  collectCoverage: true,
  collectCoverageFrom: [
    'src/**/*.{js,jsx}',
    '!src/index.js',
    '!src/**/*.stories.js',
  ],
  coverageReporters: ['text', 'lcov', 'html'],
  coverageThreshold: {
    global: {
      statements: 80,
      branches: 80,
      functions: 80,
      lines: 80,
    },
  },
};

// 运行测试并生成报告
// npx jest --coverage
//
// 输出:
// ----------|---------|----------|---------|---------
// File      | % Stmts | % Branch | % Funcs | % Lines
// ----------|---------|----------|---------|---------
// All files |   85.42 |    78.95 |   81.82 |   85.42
//  utils.js |   85.42 |    78.95 |   81.82 |   85.42
// ----------|---------|----------|---------|---------

📝 总结与展望

单元测试是保障代码质量的基石。通过本文的学习,你应该掌握了:

🎯 核心要点

  • 测试金字塔:70% 单元测试、20% 集成测试、10% E2E 测试
  • AAA 模式:Arrange(准备)、Act(执行)、Assert(断言)
  • Jest:Describe、test、expect、Matcher、Hook
  • Vitest:Vite 生态、ESM 支持、更快的执行速度
  • Testing Library:以用户为中心、避免测试实现细节
  • Mock/Stub:jest.mock()、vi.mock()、依赖隔离
  • 覆盖率:语句、分支、函数、行覆盖率
  • React 测试:RTL(render、fireEvent、waitFor)
  • Vue 测试:VTU(mount、wrapper、trigger)
  • CI/CD 集成:GitHub Actions、自动运行测试、覆盖率报告

🚀 未来展望

测试领域正在快速演进,值得关注的方向:

  • Visual Regression Testing:截图对比(Percy、Chromatic)
  • AI 生成测试:GitHub Copilot、GPT-4 生成测试用例
  • Property-Based Testing:基于属性的测试(fast-check)
  • Contract Testing:消费者驱动的合同测试(Pact)
  • Shadow Testing:生产环境并行测试(流量复制)