快照测试是将组件渲染结构序列化为文本并保存为.snap文件,后续通过比对DOM节点类型、属性、子节点顺序等检测非预期结构变更;需隔离副作用、避免替代语义断言、谨慎更新维护。

快照测试不是截图,而是把组件在特定输入下的渲染结构(比如 React 元素树)序列化成文本,保存为 `.snap` 文件;后续每次运行都会重新渲染、再比对结构是否一致。只要 DOM 节点类型、属性名、子节点顺序、key 值等有变动,快照就会失败——这能帮你快速发现非预期的结构退化,比如删了 aria-label、多套了一层 div、props 传错导致条件渲染异常。
用 render + toMatchSnapshot 写基础快照
推荐用 @testing-library/react 的 render 获取容器,再对 container 或 baseElement 调用 toMatchSnapshot():
- 确保已安装
react-test-renderer或使用 testing-library(它底层也兼容快照) - 测试文件里直接写:
expect(container).toMatchSnapshot() - 首次运行会自动生成
__snapshots__/xxx.test.js.snap,内容是格式化后的 HTML 字符串或 JSON 树
必须隔离副作用,否则快照不稳
组件里如果有未 mock 的异步操作、Date.now()、Math.random()、localStorage 读写、useEffect 里的真实请求,会导致每次渲染输出不同,快照必然失败或报错。
- 用
jest.mock('xxx')拦住所有外部模块(API、工具函数、SDK) - 固定时间:加
jest.useFakeTimers(); jest.setSystemTime(new Date('2025-01-01')) - 避免在测试中触发真实副作用;必要时用
act()包裹渲染过程
别用快照代替语义断言
快照只管“结构轮廓”,不管文字内容是否正确、按钮是否可点击、样式是否生效。它不适合验证业务逻辑或用户交互。
- 要检查某段文字是否存在?用
screen.getByText('提交') - 要确认按钮被禁用?用
expect(button).toBeDisabled() - 快照只负责回答:“这个组件在当前 props 下,渲染出来的 DOM 结构有没有意外改动?”
更新和维护快照要谨慎
快照文件是代码的一部分,要和源码一起提交、一起 Review。不能一失败就盲目 jest -u。
- 先确认变更是否合理:是功能迭代导致结构变化?还是误改引入 bug?
- 本地用
jest --watch,按i进入交互模式,选择性更新单个快照 - 避免一个 PR 更新几十个快照——说明组件耦合高或测试覆盖粒度太粗











