覆盖率虚高本质是工具统计与测试意图错位:语句被触达不等于关键路径被验证,如仅执行if真分支而忽略假分支、边界值、异常抛出及异步回调;应重点监控分支覆盖率(% Branch),当其显著低于行覆盖率(如45% vs 92%)即表明大量条件路径未覆盖。

覆盖率虚高但核心逻辑没测到,本质是工具统计和测试意图错位:语句或行数被“触达”,不代表关键路径被“验证”。比如函数调了一次、if 块进了真分支,但假分支、边界值、错误抛出、异步回调都没覆盖——数字好看,风险仍在。
看报告时重点盯“分支”和“函数”,别信“行数”
打开 Jest 生成的 HTML 报告(coverage/lcov-report/index.html),同一文件下并列显示:
- % Statements(语句)和 % Lines(行)——反映代码有没有跑过
- % Branch(分支)——反映 if/else、三元、switch 的真假路径是否都走全
- % Functions(函数)——反映导出/可调用函数是否都被执行过
当 % Branch 明显低于 % Lines(例如 45% vs 92%),说明大量条件判断只走了单边;当 % Functions 接近 100% 但 % Branch 很低,大概率是“只调不验”——函数被调用了,但里面的关键分支压根没触发。
检查测试用例是否只做“调用”,不做“断言”
常见虚高来源:写了个 test,只调用方法,不校验返回值、不模拟异常、不等异步完成。例如:
立即学习“Java免费学习笔记(深入)”;
Java项目代码review工具。分析Git变更+完整调用链路上下文,推断业务需求,进行多维度评分和分类汇总,生成完整PRD文档。包含细粒度Java代码审查清单(Null安全、异常处理、Streams、并发、equals/hashCode、资源管理、API设计、性能、MyBatis/ORM、事务边界、SQL/DD...
- 对 async 方法只写
await service.fetchData(),却没写expect(...).resolves.toEqual(...)或catch断言 - 对含 if (user.role === 'admin') 的守卫函数,只传 admin 用户,没传普通用户或空 token 场景
- 对 throw new Error('timeout') 的分支,测试里完全没触发 error 流程
这类测试能让语句和行数变绿,但实际没验证逻辑正确性。
识别“伪覆盖”的典型代码模式
以下结构容易拉高覆盖率却不保质量:
-
空 return 或提前退出:如
if (!data) return;后面有 10 行逻辑,但测试只喂了空数据 → 前面一行绿,后面全红,但报告可能因“return 那行执行了”显得覆盖尚可 - 未处理的 catch 块:try-catch 中 try 跑通了,catch 完全没进,但 catch 里的日志、降级逻辑才是容错关键
-
默认参数 + 可选链混用:如
function load(id, opts = {}) { return opts?.retry ? fetchWithRetry(id) : fetch(id); },若测试只传默认 opts,retry 分支永远沉默
用分支覆盖倒逼补全测试场景
把分支覆盖率设为硬门槛,比盯着总分更有效:
- Jest 配置中加:
"test:coverage": "jest --coverage --coverage-threshold='{\"global\":{\"branches\":85}}'" - nyc 命令加:
nyc --check-coverage --branches 85 - 目标不是 100%,而是让每个 if/else、每个三元、每个 switch case 至少有对应测试用例驱动真假路径
发现某行标红?别急着写测试,先问:这是死代码?还是真实业务路径?如果是后者,就按输入组合补用例——比如角色字段,至少要测 admin / user / null 三种。

















