Jest 与 Vitest使用指南

4 阅读5分钟

目录

  1. 为什么需要前端测试?
  2. Jest 入门教程
    • 安装与初始化
    • 编写第一个测试
    • 常用断言 API
    • 异步测试
    • Mock 函数
  1. Vitest 入门教程
    • 安装与配置
    • 第一个 Vitest 测试
    • Vitest 特性优势
  1. 实战:测试 React 组件
  2. 测试覆盖率
  3. 常见技巧与问题
  4. Jest vs Vitest 对比表
  5. 学习资源推荐
  6. 结语与建议

一、为什么需要前端测试?

在现代前端开发中,自动化测试是保障代码质量的重要手段。它能帮助我们:

  • ✅ 提高代码可靠性
  • ✅ 减少回归 Bug
  • ✅ 支持安全重构
  • ✅ 提升团队协作效率

主流测试框架对比

框架特点
JestFacebook 出品,生态成熟,广泛用于 React 项目
VitestVite 团队出品,极速启动,HMR 支持,适合现代项目

推荐新项目优先使用 Vitest,老项目可继续使用 Jest


二、Jest 入门教程

1. 安装 Jest

npm init -y
npm install --save-dev jest

若使用 TypeScript:

npm install --save-dev typescript ts-jest @types/jest

2. 配置 package.json

{
  "scripts": {
    "test": "jest",
    "test:watch": "jest --watch"
  }
}

3. 初始化配置文件

npx jest --init

选择:

  • Test environment: nodejsdom
  • Use TypeScript: Yes(如果使用 TS)
  • Coverage: Yes

生成 jest.config.js 示例:

// jest.config.js
module.exports = {
  preset: 'ts-jest',
  testEnvironment: 'node',
  collectCoverage: true,
  coverageDirectory: 'coverage'
};

4. 编写第一个测试

sum.js

function sum(a, b) {
  return a + b;
}
module.exports = sum;

sum.test.js

const sum = require('./sum');

test('adds 1 + 2 to equal 3', () => {
  expect(sum(1, 2)).toBe(3);
});

运行测试:

npm test

✅ 输出绿色表示通过。


5. Jest 常用断言(Assertions)

断言说明
expect(value).toBe(4)严格相等(===)
expect(obj).toEqual({a: 1})深度比较对象
expect(str).toContain('hello')字符串包含
expect(arr).toHaveLength(3)数组长度
expect(fn).toThrow()是否抛出异常
expect(num).toBeGreaterThan(5)大于比较

6. 分组测试:describe

describe('数学运算', () => {
  test('加法', () => {
    expect(1 + 1).toBe(2);
  });

  test('乘法', () => {
    expect(2 * 3).toBe(6);
  });
});

7. 异步测试

// fetchData.js
function fetchData() {
  return Promise.resolve('data');
}
module.exports = fetchData;

// fetchData.test.js
test('异步返回数据', async () => {
  const data = await fetchData();
  expect(data).toBe('data');
});

// 或使用 .resolves
test('resolve 匹配器', () => {
  return expect(fetchData()).resolves.toBe('data');
});

8. Mock 函数

const mockFn = jest.fn();

mockFn.mockReturnValue('hello');

expect(mockFn()).toBe('hello');
expect(mockFn).toHaveBeenCalled();
expect(mockFn).toHaveBeenCalledTimes(1);

也可模拟模块:

jest.mock('./api', () => ({
  fetchUser: jest.fn().mockResolvedValue({ name: 'Alice' })
}));

三、Vitest 入门教程

Vitest 是基于 Vite 的新一代测试框架,速度快、热更新好,API 兼容 Jest。

1. 创建 Vite 项目并安装 Vitest

npm create vite@latest my-app
cd my-app
npm install
npm install --save-dev vitest @vitest/ui jsdom

2. 配置 vite.config.ts

import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue'; // 或 react()

export default defineConfig({
  plugins: [vue()],
  test: {
    environment: 'jsdom',
    globals: true,
    setupFiles: './src/setupTest.ts',
    coverage: {
      provider: 'istanbul',
      reporter: ['text', 'json', 'html']
    }
  }
});

3. 添加脚本命令

{
  "scripts": {
    "dev": "vite",
    "test": "vitest",
    "test:ui": "vitest --ui",
    "coverage": "vitest run --coverage"
  }
}

4. 编写第一个 Vitest 测试

src/math.ts

export function add(a: number, b: number): number {
  return a + b;
}

src/math.test.ts

import { describe, expect, it } from 'vitest';
import { add } from './math';

describe('add function', () => {
  it('should return sum of two numbers', () => {
    expect(add(2, 3)).toBe(5);
  });

  it('should handle negative numbers', () => {
    expect(add(-1, 1)).toBe(0);
  });
});

运行:

npm test

启动 UI 界面(推荐):

npm run test:ui

访问 http://localhost:51204 查看可视化面板 🎉


5. Vitest 特性优势

特性说明
⚡ 极速启动基于 Vite,秒级冷启动
🔁 HMR 支持修改代码自动重跑相关测试
🖼️ 内置 UI--ui 提供图形化界面
💬 兼容 Jest API大部分语法一致,迁移成本低
🧩 原生 TS 支持无需额外插件
🧹 轻量 Mockvi.fn(), vi.spyOn()
import { vi, beforeEach, afterEach } from 'vitest';

beforeEach(() => {
  vi.useFakeTimers();
});

afterEach(() => {
  vi.useRealTimers();
  vi.clearAllMocks();
});

test('advance timers', () => {
  const cb = vi.fn();
  setTimeout(cb, 1000);
  vi.advanceTimersByTime(1000);
  expect(cb).toHaveBeenCalled();
});

四、实战:测试 React 组件

1. 安装 Testing Library

npm install --save-dev @testing-library/react @testing-library/jest-dom

2. 创建 Button 组件

src/components/Button.tsx

import { FC } from 'react';

interface ButtonProps {
  onClick: () => void;
  children: React.ReactNode;
}

const Button: FC<ButtonProps> = ({ onClick, children }) => {
  return <button onClick={onClick}>{children}</button>;
};

export default Button;

3. 编写组件测试

src/components/Button.test.tsx

import { render, screen, fireEvent } from '@testing-library/react';
import Button from './Button';

describe('Button Component', () => {
  test('渲染子内容', () => {
    render(<Button onClick={() => {}}>Click me</Button>);
    expect(screen.getByText('Click me')).toBeInTheDocument();
  });

  test('点击时调用回调函数', () => {
    const handleClick = vi.fn();
    render(<Button onClick={handleClick}>Click me</Button>);

    fireEvent.click(screen.getByText('Click me'));
    expect(handleClick).toHaveBeenCalledTimes(1);
  });
});

确保 setupTest.ts 中引入 DOM 扩展:

// src/setupTest.ts
import '@testing-library/jest-dom';

五、测试覆盖率

生成覆盖率报告

npm run coverage

输出目录:coverage/

支持格式:

  • text:终端输出
  • html:浏览器查看详细报告
  • json:CI 工具集成

配置示例:

test: {
  coverage: {
    provider: 'istanbul',
    reporter: ['text', 'json', 'html'],
    exclude: ['node_modules/', 'vite.config.ts', 'src/main.ts']
  }
}

六、常见技巧与问题

1. 控制测试执行

写法作用
test.skip()跳过该测试
test.only()只运行这个测试
describe.skip()跳过整个分组
describe.only()只运行这个分组

2. 模拟模块导入

vi.mock('../api/fetchUser', () => ({
  fetchUser: vi.fn().mockResolvedValue({ id: 1, name: 'Tom' })
}));

3. 时间控制(Fake Timers)

vi.useFakeTimers();
setTimeout(callback, 1000);
vi.advanceTimersByTime(1000); // 快进 1 秒

4. 清理 Mock

afterEach(() => {
  vi.clearAllMocks();
});

七、Jest vs Vitest 对比表

项目JestVitest
开发团队FacebookVite 团队
构建基础Node.jsVite(Rollup + ES Modules)
启动速度较慢⚡ 极快
HMR 支持
TypeScript 支持ts-jest原生支持
UI 界面无内置✅ 内置 --ui
API 兼容性-✅ 兼容 Jest 大部分语法
社区成熟度成熟稳定新兴但增长迅速
推荐场景CRA、Node.js 项目Vite、Vue、React + Vite 项目

八、学习资源推荐

官方文档

书籍与课程

  • 《Testing JavaScript with Jest》by Kent C. Dodds
  • freeCodeCamp YouTube 教程:Learn Jest in 30 Minutes
  • Udemy: Complete Intro to Unit Testing

VS Code 插件

  • Jest Runner:右键运行单个测试
  • Vitest:语法高亮 & 快捷运行
  • Error Lens:错误内联提示

九、结语与建议

📌 测试不是负担,而是对未来的投资。

✅ 掌握测试的关键路径:

  1. 从简单函数测试开始
  2. 学会使用 expectdescribe
  3. 处理异步逻辑和 Mock
  4. 进阶到组件测试
  5. 查看覆盖率,持续优化

🚀 行动建议:

  • 新项目 → 优先使用 Vitest
  • 老项目 → 可逐步迁移至 Vitest 或继续使用 Jest
  • 每写一个功能,配套写一个测试(TDD 更佳)

“你写的每一个测试,都是给未来自己的一封感谢信。” —— 某位不愿透露姓名的程序员


📥 附:完整项目模板获取

需要我为你生成一个完整的 Vite + React + TypeScript + Vitest + Testing Library 的项目模板吗?欢迎回复!


📄 文档版本:v1.0
📅 更新时间:2025年4月5日
📬 反馈建议:可通过 GitHub Issue 或私信提交


保存方式:

  • 保存为 .md 文件:testing-guide.md
  • 使用 Typora / Obsidian 打开阅读
  • 导出为 PDF 分享给团队成员

提示:复制全文粘贴到编辑器即可使用。


🎉 祝你写出健壮、可靠的前端代码,让 Bug 无所遁形!