单元测试排查分支覆盖漏洞的核心是识别所有执行路径并为每条路径编写测试用例;需结合覆盖率工具报告,重点覆盖if/else、三元操作符、逻辑短路、switch default等显性分支,以及可选链、空值合并等隐式分支。

单元测试中排查分支覆盖漏洞,核心是识别代码里所有可能的执行路径,并确保每条路径都有对应测试用例触发。覆盖率工具(如 Istanbul / nyc、Jest 内置覆盖率)能暴露“哪些 if/else、switch/case、三元表达式、逻辑运算符短路分支没被执行”,但不会自动告诉你怎么补——得靠人结合代码逻辑去分析。
看懂覆盖率报告里的“分支未覆盖”标记
多数工具会在 HTML 报告中用颜色标出分支:绿色表示已覆盖,红色或黄色表示部分/未覆盖。重点盯住以下结构:
-
if/else/if-else 链:比如
if (a > 0) { ... } else if (b < 0) { ... } else { ... },要分别构造 a>0、a≤0且b<0、a≤0且b≥0 三组输入 -
三元操作符:
status === 'active' ? 'on' : 'off'必须让 status 分别为 'active' 和非 'active' 值 -
逻辑与/或中的短路分支:
a && b()中,a 为 false 时 b() 不会执行,需单独测 a=false;c || d()中,c 为 true 时 d() 不执行,需单独测 c=true - switch 的 default 分支:即使每个 case 都覆盖了,default 没被触发也会报分支未覆盖
从函数签名和参数边界反推缺失分支
不要只盯着 if 语句本身,先看函数接受什么输入、做了什么判断。例如:
function formatPrice(price, currency) {
if (price == null) return '';
if (typeof price !== 'number') throw new Error('price must be number');
if (price < 0) return 'Free';
return `${currency}${price.toFixed(2)}`;
}
这个函数有 4 个显性分支,但测试容易只覆盖 price>0 的正常情况。实际要补:
立即学习“Java免费学习笔记(深入)”;
-
formatPrice(null, '¥')→ 触发第一个 if -
formatPrice('abc', '¥')→ 触发第二个 if(注意类型错误) -
formatPrice(-5, '¥')→ 触发第三个 if -
formatPrice(0, '¥')→ 注意 0 是 number 且不小于 0,走最后返回,也属于一个独立分支
利用断言强制验证分支行为,不只是“不报错”
很多测试只校验返回值,却忽略中间逻辑是否按预期走通。建议在关键分支点加临时日志或 spy(如 Jest 的 jest.fn()),或改用条件断言:
- 对抛异常分支,用
expect(() => fn()).toThrow(...)明确验证是否进了错误路径 - 对返回不同字符串的分支,写多个
expect(fn(x)).toBe(...)覆盖各输出结果 - 若函数内部调用了其他方法(如
logger.warn()),可 mock 它并断言是否被调用,间接证明分支执行了
警惕隐式分支:空值、NaN、对象属性缺失
JavaScript 动态类型特性制造大量隐式分支。例如:
-
if (user.profile?.avatar):需测 user 为 null、user 有但 profile 为 undefined、profile 有但 avatar 为 null/''/undefined -
arr?.[0]?.name:链式可选链本身就有多个退出点,每个 ? 都是一个潜在分支 -
value ?? 'default':value 为 null 或 undefined 时走右侧,否则走左侧,两者都需覆盖
这些场景常被忽略,却是线上偶发 bug 的高发区。建议把 “falsy 值组合” 当作常规测试用例:null、undefined、''、0、false、NaN —— 尤其注意它们在 == 与 === 下行为差异。


















