单元测试含Arrow-Kt的tailrec函数时遇NoWhenBranchMatchedException
Kotlin tailrec函数测试触发kotlin.NoWhenBranchMatchedException的原因与解决方法
异常产生的核心原因
- 递归过程中依赖调用未被完全模拟:tailrec函数会通过递归重复执行逻辑,若外部依赖在递归中被调用多次,但仅模拟了一次调用,后续未模拟的调用会返回mock框架的默认值(如
null或未定义的Either分支),导致when表达式无法匹配该返回值。 when表达式未覆盖Either的所有分支:若Either是密封类,when必须显式处理Left和Right所有子类;若使用自定义Either实现,未覆盖所有可能的子类分支,当模拟返回未处理的分支时会触发异常。- 模拟返回的
Either分支不在when处理范围内:比如模拟返回的Left携带特定值未被when的分支逻辑覆盖,导致递归进入未处理的路径。
针对性解决方法
- 匹配递归次数模拟依赖调用:先分析
tailrec函数的递归流程,确定依赖被调用的次数,对应模拟每一次调用的返回值。例如使用mockk框架时,用returnsMany批量指定多次调用的返回:
或通过计数动态返回:every { mockDependency.fetch("testId") } returnsMany listOf( Either.Left("retry"), Either.Right(42) )var retryTimes = 0 every { mockDependency.fetch("testId") } answers { if (retryTimes++ < 1) Either.Left("retry") else Either.Right(42) } - 确保
when覆盖Either所有分支:对于密封类Either,利用Kotlin的编译检查确保when处理所有子类;若为自定义Either,补充所有可能分支的处理逻辑,必要时添加else分支兜底(优先推荐显式覆盖所有分支)。 - 调试确认返回分支:在测试中添加日志,打印每次依赖调用返回的
Either类型,定位未被匹配的分支,再针对性调整模拟或when逻辑。
内容的提问来源于stack exchange,提问作者Albert Scholtz
相关产品推荐
相关产品推荐

