🃏 Jest 与单元测试
一句话定性
在 Jest 之前,搭一套前端单元测试要自己拼”跑测试的(Mocha)+ 断言的(Chai)+ mock 的(Sinon)+ 覆盖率(Istanbul)“四个零件。Jest 的杀手锏不是某项技术领先,而是”开箱即用(zero-config)“——它把这四件套打包成一个东西,让”配测试环境”这件苦差事消失了。这是一次用集成度而非技术深度取胜的典范。
一、它是什么 & 出现的时代
Jest 是 Facebook 2014 年开源的 JavaScript 测试框架(随 React 生态一起长大)。它生于 2013-2018 SPA时代:前端刚变成”软件”,急需一套像样的 unit 测试基建,但当时的方案是一堆零件的拼装游戏。
它之前的"四件套拼装"时代
- Jasmine(2010 前后):自带断言、风格优雅,是早期主流,但 mock/异步能力弱。
- Mocha(2011):只负责”组织和运行测试”(test runner),断言要配 Chai,mock 要配 Sinon,覆盖率要配 Istanbul。灵活但装配负担重。
这套组合很 Unix(小工具组合),但对”只想写个测试”的开发者太重了。
二、为什么会出现(解决上一代什么痛点)
Mocha+Chai 时代的痛点:测试还没写,环境先劝退
- 装配地狱:runner、assertion、mock、coverage 四个库各装各配,版本还要互相兼容。
- 没有内建 mock:测前端必须 mock 网络/模块,Sinon 要单独学一套 API。
- 没有快照能力:UI 组件渲染出一大坨结构,逐字段断言极其啰嗦。
- 慢:大型套件串行跑,反馈周期长。
本质矛盾:前端测试的真正成本不在”写断言”,而在”把环境搭起来”。 没人来消灭这个固定成本。
Jest 的回答:全都给你内建好,一个 jest 命令什么都有。
三、核心机制 & 为什么流行
Jest 统治的三个真正原因
① 零配置、All-in-one(最关键) 断言(
expect)、mock(jest.fn()/jest.mock())、快照、覆盖率(--coverage)、并行执行——全部内建。npm i -D jest即可开测,固定成本被打到接近零。② 快照测试(snapshot)——当年的杀手级特性 第一次跑,把组件渲染结果序列化存进
__snapshots__;之后每次跑都和存档比对,变了就报警。“一行toMatchSnapshot()顶一百行手写断言”,对 UI 测试极有吸引力。③ 与 React 生态深度绑定 Facebook 出品,CRA(Create React App)默认集成,文档/示例全用 Jest。生态惯性让它成了事实标准。
④ 并行 + 智能调度 多 worker 进程并行跑、按上次失败优先、watch 模式只跑受影响的测试,反馈快。
Mocha+Chai+Sinon+Istanbul(自己拼):
装 4 个库 ─► 写 4 套配置 ─► 互相兼容调试 ─► 才能写第一个测试
Jest(一体化):
npm i -D jest ─► 直接写测试 ◄── 固定成本 ≈ 0
快照测试到底怎么工作
首跑: render(<Button/>) ──► 序列化 ──► 写入 Button.test.js.snap(存档)
再跑: render(<Button/>) ──► 序列化 ──► 与存档 diff
├─ 一致 ──► ✅ 通过
└─ 不一致 ──► ❌ 报警:要么你改对了(`-u` 更新),要么是回归
四、带来的新问题 / 副作用
Jest 的代价,一半出在它最骄傲的特性上
① 快照测试容易堕落成”盲目更新(blind update)” 这是快照最大的争议。测试一红,开发者不去想”我是不是改坏了”,而是顺手
jest -u把快照刷新成当前输出——测试从”守门员”变成”橡皮图章”。快照越大越没人读,越没人读越无脑更新,信心归零。② 跑在 Node + jsdom,不是真浏览器 Jest 默认用 jsdom(JS 模拟的 DOM)。它没有真实布局引擎、没有真实事件循环、没有真正的
getBoundingClientRect、CSS 不生效。**“jsdom 里绿,真浏览器里崩”**是常见陷阱——这正是 测试金字塔→奖杯里”unit 离用户太远、信心不足”的具体体现。③ 配置随项目变大而变重 一旦用上 TypeScript、JSX、CSS Modules、路径别名,就要配
babel-jest/ts-jest、transform、moduleNameMapper……当初引以为傲的”零配置”被现实侵蚀,大项目的jest.config.js能长到上百行。④ 自带转换管线,与现代构建工具不一致 Jest 用自己的一套转换(babel-jest 等),和应用真正的构建管线(Webpack/Vite)是两条路——埋下了 Vitest 取代它的伏笔。
五、为什么会衰落 / 现状
Jest 没有”衰落”,在 Webpack/CRA/Next.js 体系里仍是绝对主流。但在新生的 Vite 生态里,它正被 Vitest 系统性替换。
衰退的精确边界:不是技术不行,是"工具链分裂"
现状(2026):Jest 仍在维护、装机量巨大(存量项目),但新项目尤其是 Vite 项目,默认已倒向 Vitest。
六、对后续技术的影响(因果链)
Mocha+Chai+Sinon+Istanbul(拼装,装配地狱)
│
▼ 痛点:固定成本在"搭环境"
Jest(2014, FB):zero-config + 一体化 ──► 抹平固定成本,成为事实标准
│
├─► 快照测试:普及"一行顶百行" ──► 但堕落成盲目更新(副作用)
│
├─► jsdom 模拟环境 ──► 快,但"离真浏览器有差"(信心折扣)
│ └─► 推动 [[Testing-Library与组件测试]] 强调"测行为"、推动 E2E 补真实性
│
├─► 配置随规模变重 ──► "零配置"被侵蚀
│
└─► 自带转换管线,与 [[Vite]] 不一致 ──► 工具链分裂
│
▼
[[Vitest]](2021):复用 Vite 管线 + 兼容 Jest API,在 Vite 生态接棒
历史地位
🔗 相关:前端测试演进史 | Vitest | Testing-Library与组件测试 | E2E测试-Cypress与Playwright 🔗 工程化:Vite | Webpack | TypeScript | 为什么Vite能取代Webpack 🔗 运行时:Node.js | 框架:React 🔗 时代:2013-2018 SPA时代 | 2018-2023 工程化时代