避免断言遗漏的关键是显式验证每个可观察行为,包括状态变化、调用次数、错误类型、执行顺序及异步副作用;覆盖成功、http错误、网络异常等所有分支;借助日志、mock、fake timers 和 hasassertions 等手段锁定执行细节,杜绝“无报错即通过”。

避免断言遗漏的关键是让每个可观察行为都有对应验证,不依赖“看起来正常”或“没报错”来判断通过。重点在于显式检查状态变化、调用次数、错误类型和执行顺序,而不是只看最终返回值。
明确验证异步副作用
异步操作常伴随 loading 开关、日志打印、埋点上报等副作用,这些容易被忽略:
- 用 jest.fn() 替换副作用函数(如 logError、trackEvent),断言 mockFn.mock.calls.length 是否为预期值
- React 中配合 act() 包裹异步操作,再检查 state 是否更新(如 expect(loading).toBe(false))
- loading 状态不仅要验终值,还要验时机:请求发起时是否立即设为 true,响应后是否准确设回 false
覆盖所有分支路径的断言
一个网络请求或重试逻辑至少有成功、HTTP 错误、网络异常三类出口,每类都需独立断言:
- 成功路径:验证数据解析结果、UI 渲染内容、loading 关闭、副作用是否触发
- HTTP 错误(如 404):断言是否进入 catch、是否抛出自定义错误、错误 message 是否含状态码
- 网络异常(如 fetch 失败):确认 Promise 被 reject、是否有兜底提示、重试计数是否递增
- 不要只写一个 .resolves 测试就认为流程完整
用时间与调用痕迹锁定执行细节
微任务顺序、重试延迟、链式中断等行为无法靠肉眼判断,必须靠可观测痕迹验证:
- 用数组收集执行日志:log.push('start')、then(() => log.push('then-1')),最后比对完整序列
- 重试测试中,启用 jest.useFakeTimers() 后,用 jest.runAllTimers() 或 jest.advanceTimersByTime() 推进,并断言 mockFetch.mock.calls.length 符合重试次数
- 链式调用中,给每一步插入轻量钩子(如 onTransform: jest.fn()),确保中间环节被调用且参数正确
拒绝“无报错即通过”的侥幸心理
未处理的 rejection、静默失败、Promise resolve 了但数据为空——这些都不会让测试直接报错,却代表逻辑缺陷:
- 对 async 函数,必须用 await expect(...).resolves 或 .rejects,不能只调用不 await
- 测试后加一句 expect.hasAssertions(),强制要求至少有一个 expect 执行,防止单纯调用后测试提前结束
- 开启 Jest 的 errorOnUnhandledRejection: true 配置,让未捕获的 Promise reject 直接导致测试失败
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











