提高防御性代码覆盖率的关键是主动模拟失败场景并验证兜底行为,包括网络/ dom /第三方 api 异常、空值与类型错位输入,确保每条容错路径可观察、可断言,并通过分支覆盖率精准识别未覆盖的 else/catch/default 分支。

提高防御性代码(比如异常兜底分支)的代码覆盖率,关键不是“多写几个 try/catch”,而是让每一条容错路径都被真实触发、验证并反馈。否则,那些 catch 块、else 分支、if (!data) 判断,很可能常年静默,成了“僵尸逻辑”。
显式模拟各种失败场景,而不是等它自然发生
防御性代码的价值在于应对异常,但测试时不能靠“祈祷线上出错来覆盖”。必须主动构造失败条件:
- 对网络请求兜底:用 Mock 工具(如 MSW 或 Jest mock)返回 408、500、超时、空响应体,验证
catch中的错误提示、默认值赋值、重试逻辑是否执行 - 对 DOM 操作兜底:mock
document.getElementById返回null,检查容器判空逻辑(如el && el.innerHTML = ...)是否生效,避免脚本中断 - 对第三方 API 兜底:模拟
navigator.clipboard为undefined或writeText()抛NotAllowedError,确保降级到textarea + execCommand的分支被调用
覆盖“空值流”和“类型错位流”
防御性代码常围绕输入校验展开,但测试容易只覆盖“正常输入”,漏掉真正危险的边界:
- 传入
null、undefined、''、{}、[]、NaN等非预期值,验证函数是否返回合理默认值(如str?.trim() || 'default') - 故意传错类型:比如该传
number却传'123'字符串,检查isNaN()、Number.isInteger()或类型转换逻辑是否拦截并处理 - 对嵌套对象取值做兜底:测试
user?.profile?.avatar?.url在任意层级为null时,是否回退到占位图或不渲染
确保兜底行为可观察、可断言
光让兜底代码“跑过”没用,必须验证它真的起了作用:
- 在
catch块里修改了状态(如loading = false、error = true),测试中要断言这些状态变更已发生 - 兜底时显示 toast 或更新按钮文字,需通过测试库(如 React Testing Library)查询对应 DOM 文本是否出现
- 兜底触发了日志上报(如
console.error或 Sentry.captureException),可用jest.spyOn(console, 'error')检查是否被调用
用分支覆盖率倒逼补全逻辑缺口
行覆盖率会骗人——if (x) { a() } else { b() } 只测 if 分支,行数照样绿,但 else 是盲区。防御性代码恰恰大量依赖这类判断:
- 运行测试时开启分支覆盖率(如 Jest 的
--coverage --coverage-reporters=html),重点查看红色未覆盖的else、catch、default块 - 对每个
??、&&、||、三元表达式,确保左右两侧都至少有一个测试用例触发 - 工具如 Istanbul 的 HTML 报告能直接定位哪一行哪个分支没走,比盯着数字高效得多











