Appearance
Jest 单元测试:前端开发者的代码守护神
更新: 6/14/2026 字数: 0 字 时长: 0 分钟
一、从一个真实的开发痛点说起
你写了一个工具函数 formatPrice,把数字格式化成价格。本地手动试了几个数,看着没问题,就提交上线了。
三周后,产品迭代,同事改动了相邻的代码,顺手"优化"了你的函数。结果线上出现了 ¥NaN,用户投诉,你被拉进群里背锅——可你明明三周前测过啊。
问题在于:手动测试是一次性的,人一走它就失效了。 你需要一个"永远在岗、每次改代码都自动帮你重测一遍"的机器人。这个机器人,就是 Jest。

二、什么是 Jest
Jest 是由 Meta(原 Facebook)开源的一款 JavaScript 测试框架。它的定位很明确:让你用极少的配置,就能给前端代码写自动化测试。
所谓"单元测试",就是把代码拆成一个个最小的"单元"(通常是一个函数、一个组件),单独验证每个单元"输入什么、就该输出什么"。Jest 就是帮你写、跑、管这些单元测试的工具。
它之所以成为前端测试的事实标准,靠的是这几个特点:
- 开箱即用:自带测试运行器、断言库、Mock 工具、覆盖率统计,装一个就够,不用东拼西凑。
- 零配置起步:大部分项目装完就能跑,不用折腾一堆配置文件。
- 快:自动并行跑测试,还能只跑"改动相关"的那部分。
- 生态好:配合 React Testing Library、Vue Test Utils 等,能测组件、测交互。
一句话定义:Jest 是一个开箱即用的 JavaScript 测试框架,帮前端开发者把"代码该有的行为"写成可自动执行的检查,每次改动后一键验证。
三、为什么前端开发者需要它

1. 提前抓虫,把 bug 挡在上线前
测试在你本地、在 CI 流水线里就跑了。函数逻辑一旦写错,测试立刻飘红,根本到不了用户面前。
2. 重构不慌
想优化一段陈年老代码却不敢动?只要测试齐全,你大胆改,改完跑一遍测试,全绿就说明行为没变,红了就说明你改坏了。测试是重构的安全网。
3. 测试即"活文档"
一份好的测试用例,清楚写明了"这个函数在各种输入下应该返回什么"。新人接手代码,看测试就能秒懂函数的预期行为,比注释还可靠——因为注释会过期,测试不会(过期了就飘红了)。
4. 跨团队协作更放心
多人协作时,别人改了公共模块,你的测试会替你"站岗"。谁改坏了你的功能,提交时测试立刻报警。
四、五分钟跑起第一个测试
第 1 步:安装
bash
npm install --save-dev jest在 package.json 里加一条脚本:
json
{
"scripts": {
"test": "jest"
}
}第 2 步:写一个被测函数
新建 sum.js:
javascript
function sum(a, b) {
return a + b;
}
module.exports = sum;第 3 步:写测试文件
新建 sum.test.js(Jest 会自动识别 .test.js 或 .spec.js 结尾的文件):
javascript
const sum = require('./sum');
test('1 加 2 应该等于 3', () => {
expect(sum(1, 2)).toBe(3);
});第 4 步:运行
bash
npm test你会看到一行绿色的 ✓ 1 加 2 应该等于 3。恭喜,你的第一个自动化测试跑通了。
这三行测试代码里藏着 Jest 最核心的三件套:
test()定义一个测试用例,expect()包裹"实际结果",toBe()是"匹配器",声明你期望的值。
五、读懂一个测试的骨架:AAA 法则

写测试别东一榔头西一棒子,业界公认的清晰结构叫 AAA 法则,任何一个测试都能拆成这三段:
- Arrange(准备):准备好测试要用的数据和环境。
- Act(执行):调用被测的那个函数/方法。
- Assert(断言):检查结果是不是和预期一致。
javascript
test('购物车计算总价', () => {
// Arrange 准备数据
const cart = [
{ name: '苹果', price: 5, count: 2 },
{ name: '牛奶', price: 10, count: 1 },
];
// Act 执行操作
const total = calculateTotal(cart);
// Assert 断言验证
expect(total).toBe(20);
});养成这个习惯,你的测试别人一眼就能读懂。
组织测试:describe 与常用钩子
用 describe 把相关的测试归到一组,用钩子函数处理重复的准备/清理工作:
javascript
describe('用户模块', () => {
beforeEach(() => {
// 每个测试运行前都会执行,常用来重置数据
});
afterEach(() => {
// 每个测试运行后执行,常用来清理
});
test('能正确创建用户', () => { /* ... */ });
test('能正确删除用户', () => { /* ... */ });
});六、常用匹配器(Matchers)速查
匹配器就是 expect(...) 后面跟的那个判断方法,决定你"怎么比"。下面是高频的几类:
| 匹配器 | 含义 | 示例 |
|---|---|---|
toBe | 严格相等(适合数字、字符串) | expect(2 + 2).toBe(4) |
toEqual | 值相等(适合对象、数组,递归比较内容) | expect(obj).toEqual({ a: 1 }) |
toBeTruthy / toBeFalsy | 是否为"真值"/"假值" | expect(value).toBeTruthy() |
toContain | 数组/字符串是否包含某项 | expect(list).toContain('apple') |
toThrow | 是否抛出异常 | expect(() => fn()).toThrow() |
toHaveBeenCalled | 函数是否被调用过(配合 Mock) | expect(mockFn).toHaveBeenCalled() |
not | 取反,接在前面 | expect(1).not.toBe(2) |
小坑提醒:比较对象或数组时,千万别用
toBe(它比的是"是不是同一个引用"),要用toEqual(比的是"内容是否一样")。这是新手最常踩的雷。
七、处理异步代码
前端到处是异步(接口请求、定时器)。Jest 测异步有两种常见写法:
async / await(最推荐,可读性最好):
javascript
test('能获取到用户数据', async () => {
const data = await fetchUser(1);
expect(data.name).toBe('张三');
});测试 Promise:
javascript
test('请求成功返回数据', () => {
return expect(fetchUser(1)).resolves.toHaveProperty('name');
});关键点:异步测试一定要
await或return,否则 Jest 不会等异步结束,测试会"假通过"——这是另一个高频坑。
八、Mock:用"替身"隔离外部依赖

单元测试讲究"只测自己这一块"。可你的函数往往要调接口、读数据库——这些又慢又不稳定,还可能没网。怎么办?用 Mock(模拟),给真实依赖找个"替身"。
Mock 的作用,就是把真实的外部依赖换成一个你能完全掌控的假对象:让它想返回什么就返回什么,瞬间响应,还能记录"它被调用了几次、传了什么参数"。
模拟一个函数:
javascript
test('点击按钮会触发回调', () => {
const mockCallback = jest.fn(); // 造一个假函数
handleClick(mockCallback);
expect(mockCallback).toHaveBeenCalled(); // 验证被调用了
expect(mockCallback).toHaveBeenCalledTimes(1); // 验证调用了 1 次
});模拟一个接口请求模块:
javascript
jest.mock('./api'); // 把整个 api 模块替换成 Mock
import { fetchUser } from './api';
test('展示用户名', async () => {
fetchUser.mockResolvedValue({ name: '李四' }); // 指定假返回
const name = await getUserName(1);
expect(name).toBe('李四');
});这样一来,测试不依赖真实网络,又快又稳定,还能轻松模拟"接口报错"这种平时难复现的场景。
九、测试覆盖率:看看哪里还没测到

跑测试时加个参数,Jest 会生成一份"覆盖率报告",告诉你代码有多少被测到了:
bash
npx jest --coverage报告里有几个关键指标:
- 语句覆盖(Statements):有多少行代码被执行到了。
- 分支覆盖(Branches):
if/else、三元运算的每个分叉都走到了吗。 - 函数覆盖(Functions):有多少函数被调用过。
- 行覆盖(Lines):覆盖到的代码行比例。
理性看待覆盖率:它能帮你发现"完全没被测到的死角",但高覆盖率 ≠ 高质量。100% 覆盖也可能断言写得敷衍。把它当"地图"用,优先覆盖核心逻辑,别为了凑数字写无意义的测试。
十、给前端的实战建议
- 从工具函数开始:纯函数(给定输入必有固定输出)最好测,先从
utils目录练手,最容易获得成就感。 - 测行为,别测实现细节:测"用户点击后看到了什么",而不是"内部某个变量变成了几"。这样重构时测试才不会动不动就崩。
- 一个测试只验证一件事:用例小而专注,失败时一眼就知道哪儿坏了。
- 测试名写成人话:
test('价格为负数时应抛出错误')远胜test('test1')。 - 配合 CI 自动跑:把
npm test接入提交/合并流程,让测试成为代码进主干前的强制关卡。 - 别追求 100% 覆盖:核心逻辑、易错边界重点测;一些简单的样板代码不必强求。
十一、一句话总结
Jest 之于前端,就像一个不知疲倦、永远在岗的代码质检员。你只需把"代码本该如何表现"写成一条条测试,它就会在你每次改动后自动重跑一遍,替你守住质量底线。写测试当下看似多花了几分钟,换来的是日后重构的底气和半夜不被报警电话叫醒的安稳——这笔投资,前端开发者越早开始越划算。