You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Kotlin协程异常测试求助:添加withContext后断言失败

问题排查与解决方案

问题核心分析

断言失败的本质是预期的异常实例与实际捕获的异常实例不是同一个对象——RuntimeException默认使用引用相等判断,即便类型和消息完全一致,只要不是同一个实例,assertEquals就会失败,这也是你看到错误信息里两个异常类型完全相同但断言失败的原因。

可能触发原因

  1. 未使用针对Kotlin协程优化的Mockito扩展,模拟suspend函数时异常被隐式包装或创建新实例;
  2. Flow的last()方法在调度时序上未完全等待异常处理流程完成;
  3. 测试中dummyException的生命周期问题(例如每次测试重新创建实例,但断言引用旧实例)。

具体解决方案

方案1:修改断言逻辑,不依赖引用相等

放弃实例引用断言,改为检查异常的类型和业务标识(如消息):

// Then
Assert.assertEquals(dummyException.javaClass, result.exception.javaClass)
Assert.assertEquals(dummyException.message, result.exception.message)

方案2:使用Mockito-Kotlin处理suspend函数的异常模拟

标准Mockito对Kotlin suspend函数的支持不完善,需引入mockito-kotlin依赖,使用coWhenever替代whenever:

// 修改givenFailure方法
private suspend fun givenFailure(){
    coWhenever(mockDSR.getCategories()).thenThrow(dummyException)
}

方案3:显式收集Flow所有结果,避免时序问题

将last()改为toList().last(),确保Flow的所有发射(包括Loading和Failure)都完成后再获取结果:

// When
val result = sut().toList().last() as ResultOf.Failure

额外检查项

确保测试类中dummyException是全局单实例,而非每次测试/setup重新创建:

// 定义在测试类顶层,而非@Before方法内
private val dummyException = RuntimeException("测试异常")

内容的提问来源于stack exchange,提问作者Rizki Rakasiwi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 07:35:23