Jest 单元测试入门指南
Jest 测试入门:安装配置、断言、用例过滤、Mock、生命周期钩子与覆盖率,并说明原生 ESM 的运行参数和模块 Mock 差异。
本文依据官方文档整理,未执行运行验证或性能基准。代码片段展示局部用法,业务函数、数据和环境需按项目补齐;版本与配置以所引文档为准。
直接回答:Jest 是一个功能齐全的 JavaScript 测试框架,内置测试运行器、断言、快照和 Mock 能力,可用于 Node.js 后端和前端组件测试;ESM、TypeScript、JSX 与 DOM 环境需要按项目配置。
为什么是 Jest
在 JavaScript 测试领域,Jest 的杀手锏是"全家桶"体验:别的框架需要你分别挑选运行器、断言库、Mock 库再拼装,Jest 一次性全部内置,并且默认约定(__tests__ 目录、.test.js 后缀)让新项目几分钟内就能跑起第一条测试。
初始化项目
mkdir jest-demo && cd jest-demo
npm init -y
npm install --save-dev jest
在 package.json 中补上测试脚本:
{
"scripts": {
"test": "node --experimental-vm-modules node_modules/jest/bin/jest.js"
}
}
本文例子使用原生 ES Modules:需要 npm pkg set type="module" 并用上面的 npm test 脚本运行;若配置了代码转换器,须使其输出 ESM 或关闭 transform——Jest 对 ESM 的支持目前仍是实验性特性。
编写第一条测试
先写个被测函数 math.js:
export function add(a, b) {
return a + b;
}
再建 __tests__/math.test.js:
import { add } from "../math.js";
describe("add 函数", () => {
it("1 + 2 应该等于 3", () => {
expect(add(1, 2)).toBe(3);
});
});
describe 用来分组相关用例,it 定义单条用例,expect(...).toBe(...) 完成断言——这三个全局函数由 Jest 自动注入,无需 import。npm test 即可运行。
只跑想跑的测试
npm test -- math:按文件名过滤;npm test -- -t "应该等于 3":按用例名过滤;it.only(...)/describe.only(...):临时只跑标记的用例(提交前记得去掉)。
调试某个失败用例时,这几个技巧能省大量时间。
Mock:隔离外部依赖
原生 ESM 中需显式导入 jest;CommonJS 的 jest.mock 提升机制不能直接套到静态 ESM import。以下是模块 mock 与函数 spy 的局部示例(service 由项目提供):
import { jest } from "@jest/globals";
jest.unstable_mockModule("../api.js", () => ({
fetchUser: jest.fn().mockResolvedValue({ id: 1 }),
}));
const api = await import("../api.js"); // 注册后动态导入,包含它的被测模块也需随后导入
const fn = jest.fn(); // 2. 独立 Mock 函数
fn.mockReturnValue(42);
fn.mockResolvedValue({ id: 1 }); // 异步版本
jest.spyOn(service, "fetch") // 3. 间谍:保留原实现、监听调用
.mockImplementation(() => "fake");
配合 expect 的调用断言验证交互;afterEach 中用 jest.restoreAllMocks 恢复 spy。spyOn 默认调用原实现,示例的 mockImplementation 则主动替换了实现。
Setup 与 Teardown 钩子
beforeAll(() => { /* 套件开始前一次:连数据库 */ });
beforeEach(() => { /* 每条用例前:重置数据 */ });
afterEach(() => { /* 每条用例后:清理现场 */ });
afterAll(() => { /* 套件结束后一次:断开连接 */ });
记住黄金法则:每条用例都应能独立运行,依赖执行顺序的测试迟早变成维护噩梦。
代码覆盖率
npx jest --coverage
会生成语句/分支/函数/行四个维度的覆盖率报告,并在 coverage/ 下产出 HTML 可视化。覆盖率是参考而非目标——盯着百分比不如盯着"关键路径是否都有用例"。
常见问题(FAQ)
Q:Jest 和 Vitest 怎么选?
A:Vitest 与 Vite 生态无缝、原生 ESM 与 Vite 配置复用,新项目(尤其 Vite 项目)优先考虑;Jest 生态更成熟、资料更多,存量项目继续用没问题。
Q:快照测试(Snapshot)值得用吗?
A:适合输出结构稳定但内容冗长的场景(如组件渲染结果)。警惕"盲更新快照"——更新前务必人工确认 diff 是预期变更。
Q:测试跑得很慢怎么办?
A:先用 --runInBand 排查是不是并行导致的资源争抢;再用 --maxWorkers 调并发;把重型集成测试拆到独立 job,单元测试保持秒级。
官方参考
资料核对日期:2026-09-29。