Jest 是Facebook 开发的一个功能强大的 JavaScript 测试框架,特别适合 Node.js 和前端项目。
特点:
✅ 零配置:开箱即用,无需复杂配置
✅ 快照测试:自动保存和比较组件输出
✅ Mock 功能:强大的模块和函数模拟能力
✅ 代码覆盖率:内置覆盖率报告
✅ 并行执行:测试运行速度快
以下是其详细介绍及指南:
一、安装
npm install jest supertest --save-dev
supertest 是专门用来测试 Express/Koa 接口的工具。
二、Jest 核心概念
(1) 测试结构
测试文件通常以.test.js结尾,使用test或it函数定义测试用例,test接收两个参数,一个是描述测试用例的字符串,一个是包含测试代码的回调函数。
js
test("adds 1 + 2 to equal 3",
() => { expect(sum(1, 2)).toBe(3); }
)
(2) 断言与匹配器
通过expect函数进行断言,它接受一个值作为参数,并返回一个包含各种断言方法的对象。
匹配器用于验证测试结果,如toBe用于严格相等性检查,相当于===;toEqual用于深度相等性检查,适用于对象和数组等复杂数据类型;还有toBeNull、toBeUndefined、toBeGreaterThan等多种匹配器。
常用断言:
js
expect(value).toBe(expected) // 严格相等 (===)
expect(value).toEqual(expected) // 深度相等
expect(value).toBeTruthy() // 真值
expect(value).toBeFalsy() // 假值
expect(value).toBeNull() // null
expect(value).toBeDefined() // 不是 undefined
expect(array).toContain(item) // 数组包含
expect(fn).toThrow() // 函数抛出异常
(3) 测试套件
可使用describe函数将相关的测试用例组合在一起,形成测试套件。
describe("test query", () => { test("query3", () => { expect(Pencil.query("hello", "?hello=test")).toBe("test"); }); })
三、Jest 高级功能
(1) 生命周期钩子
Jest 提供了多个生命周期钩子函数,用于在测试的不同阶段执行代码:
js
// 在所有测试之前运行一次
beforeAll(() => {
console.log('在所有测试之前运行');
});
// 在每个测试之前运行
beforeEach(() => {
// 重置测试状态
});
// 在每个测试之后运行
afterEach(() => {
// 清理工作
});
// 在所有测试之后运行一次
afterAll(() => {
console.log('在所有测试之后运行');
});
(2) Mock 函数详解
Jest 的 Mock 功能非常强大,可以模拟函数、模块和类:
js
// 创建 Mock 函数
const mockFn = jest.fn();
// 设置返回值
mockFn.mockReturnValue(42);
// 设置实现
mockFn.mockImplementation((a, b) => a + b);
// 验证调用情况
expect(mockFn).toHaveBeenCalled();
expect(mockFn).toHaveBeenCalledTimes(3);
expect(mockFn).toHaveBeenCalledWith('arg1', 'arg2');
// Mock 模块
jest.mock('./module', () => ({
fetchData: jest.fn(() => Promise.resolve('data'))
}));
(3) 异步测试
Jest 支持多种异步测试方式:
js
// Promise 方式
test('async test with promise', () => {
return fetchData().then(data => {
expect(data).toBe('expected data');
});
});
// Async/Await 方式
test('async test with async/await', async () => {
const data = await fetchData();
expect(data).toBe('expected data');
});
// 回调函数方式
test('async test with callback', done => {
fetchData(data => {
expect(data).toBe('expected data');
done(); // 必须调用 done()
});
});
(4) 快照测试(Snapshot Testing)
快照测试用于确保 UI 或数据结构不会意外更改:
js
// 组件快照测试
test('renders correctly', () => {
const tree = renderer.create(<MyComponent />).toJSON();
expect(tree).toMatchSnapshot();
});
// 对象快照测试
test('object snapshot', () => {
const obj = {
id: 1,
name: 'Test',
data: [1, 2, 3]
};
expect(obj).toMatchSnapshot();
});
// 更新快照:运行 jest --updateSnapshot 或 jest -u
四、配置与最佳实践
(1) Jest 配置文件
创建 jest.config.js 进行自定义配置:
js
module.exports = {
// 测试环境
testEnvironment: 'node', // 或 'jsdom' 用于前端测试
// 测试文件匹配模式
testMatch: ['**/__tests__/**/*.js', '**/?(*.)+(spec|test).js'],
// 覆盖率配置
collectCoverage: true,
collectCoverageFrom: [
'src/**/*.js',
'!src/**/*.test.js',
'!src/index.js'
],
coverageThreshold: {
global: {
branches: 80,
functions: 80,
lines: 80,
statements: 80
}
},
// 模块别名(配合 webpack 或 babel)
moduleNameMapper: {
'^@/(.*)$': '<rootDir>/src/$1'
},
// 测试前执行的脚本
setupFilesAfterEnv: ['<rootDir>/jest.setup.js'],
// 忽略的路径
testPathIgnorePatterns: ['/node_modules/', '/dist/']
};
(2) 测试最佳实践
-
测试命名规范
- 测试文件:ComponentName.test.js 或 ComponentName.spec.js
- 测试描述:使用 "should ... when ..." 格式
-
测试组织原则
- 每个测试只关注一个功能点
- 使用 describe 进行逻辑分组
- 避免测试间的依赖关系
-
Mock 使用原则
- 只 Mock 外部依赖(API、数据库、文件系统)
- 避免过度 Mock,保持测试的真实性
- 使用 jest.spyOn() 进行部分 Mock
-
异步测试注意事项
- 确保正确处理 Promise 拒绝
- 设置合理的超时时间
- 使用 async/await 提高可读性
五、常见问题与调试技巧
(1) 调试测试
bash
# 使用 Chrome DevTools 调试
node --inspect-brk node_modules/.bin/jest --runInBand
# 使用 VS Code 调试
# 在 .vscode/launch.json 中添加:
{
"type": "node",
"request": "launch",
"name": "Jest Tests",
"program": "${workspaceFolder}/node_modules/.bin/jest",
"args": ["--runInBand"],
"console": "integratedTerminal"
}
(2) 性能优化
bash
# 只运行更改的测试
jest --onlyChanged
# 根据测试文件大小排序运行
jest --testSequencer=@jest/test-sequencer
# 使用缓存加速
jest --cache
# 并行执行(默认开启)
jest --maxWorkers=4
(3) 常见错误处理
- Timeout 错误:增加 jest.setTimeout(10000)
- 模块找不到:检查 moduleNameMapper 配置
- 环境变量问题:使用 dotenv 或 setupFiles 配置
- 内存泄漏:使用 --logHeapUsage 检测
六、与其他工具集成
(1) TypeScript 支持
bash
npm install ts-jest @types/jest typescript --save-dev
jest.config.js:
js
module.exports = {
preset: 'ts-jest',
testEnvironment: 'node',
};
(2) React 测试
bash
npm install @testing-library/react @testing-library/jest-dom --save-dev
jest.setup.js:
js
import '@testing-library/jest-dom';
(3) Vue 测试
bash
npm install @vue/test-utils vue-jest --save-dev
(4) 与 CI/CD 集成
yaml
# GitHub Actions 示例
name: Tests
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v2
with:
node-version: '16'
- run: npm ci
- run: npm test
- run: npm run test:coverage
七、学习资源
- 官方文档:https://jestjs.io/
- 中文文档:https://jestjs.io/zh-Hans/
- GitHub 仓库:https://github.com/facebook/jest
- 社区插件 :
- jest-extended:扩展匹配器
- jest-dom:DOM 测试匹配器
- jest-watch-typeahead:文件名过滤
- 推荐书籍:《Testing JavaScript Applications》
总结
Jest 作为现代 JavaScript 测试框架,提供了完整的测试解决方案。掌握其核心概念后,应深入学习高级功能如 Mock、异步测试、快照测试等,并结合项目实际情况制定合适的测试策略和配置方案。定期运行测试、维护测试代码质量,是保证项目稳定性的关键。