Angular单元测试中匿名箭头函数如何实现全语句覆盖
匿名箭头函数全语句覆盖实现方法
测匿名箭头函数卡语句覆盖是单测里非常常见的问题,核心问题基本都是两类:要么你根本没拿到箭头函数本身的引用,只测了外层包裹方法的主流程;要么你漏了箭头函数内部的分支、边界场景触发。
按下面的步骤调整就能拿满覆盖:
- 先解决函数引用问题
如果箭头函数是完全内联写在方法参数、对象属性里的(比如Promise.then(res => { 一堆逻辑 })、arr.filter(x => { 一堆判断 })),测试环境根本没法直接拿到这个函数的引用单独造场景测,最稳妥的处理方式是把箭头函数抽成同作用域下的常量,生产环境逻辑完全不变,测试环境可以单独导出拿到引用:
不想改业务代码抽函数的话,也可以在测试里调用外层方法时,用spyOn方法劫持对应方法的回调参数,拿到内联箭头函数的引用再测,但这种方式稳定性差,业务代码改下参数顺序用例就挂,更推荐抽常量的方式。// 原写法(难覆盖) export const getProcessedList = (rawList) => { return rawList.map(item => { if (!item) return { empty: true } if (item.deleted) return { removed: true } return { data: item.value } }) } // 调整后写法(易覆盖,生产逻辑无变化) const listItemAdapter = item => { if (!item) return { empty: true } if (item.deleted) return { removed: true } return { data: item.value } } export const getProcessedList = (rawList) => rawList.map(listItemAdapter) // 测试环境可单独导出listItemAdapter,直接对这个函数写用例 - 逐行核对触发所有可执行语句
语句覆盖要求每一行可执行代码至少被执行一次,你对着箭头函数的代码逐行列场景就行:- 所有条件判断(if、三元、switch、可选链兜底)的真假分支都要跑到,不能只测正常传参的happy path
- 所有异常分支、兜底返回、throw错误的场景都要造对应入参触发,比如入参传null、undefined、类型错误的值、不符合业务规则的值
- 如果箭头函数是异步的,一定要等异步逻辑执行完再结束用例,async箭头函数要加await,回调形式的要等done触发,不然异步里的代码根本没跑,覆盖率自然算不到
- 排查覆盖率工具的误判
如果逻辑上你已经把所有代码都跑到了,覆盖率还是显示缺语句,查这几个常见坑:- 不要mock整个包含目标箭头函数的模块,mock之后原函数代码根本不会执行,不会算覆盖
- 不要在测试里自己写个逻辑一样的箭头函数测,必须跑业务代码里的原函数才算
- 检查插桩配置,确保单测跑的是和覆盖率插桩同一份的源码,不要出现构建转译后源码映射错位的问题
大部分人卡覆盖的核心原因都是只测了外层方法的正常场景,箭头函数里的异常判断、边界分支从来没被触发过,只要把这些场景的入参补上,覆盖很容易拉满。
内容的提问来源于stack exchange,提问作者André Castro
相关产品推荐
相关产品推荐

