解决Mockito Mock带Raise<BusinessError>上下文接收器服务返回null问题
Mockito Mock带上下文接收器方法返回Null的解决方案
问题背景
测试依赖ServiceTwo的ServiceOne服务时,ServiceTwo的call方法带有Raise<BusinessError>上下文接收器。使用Mockito mock ServiceTwo后,测试代码中直接调用mock的call方法能返回预期值,但ServiceOne内部调用该mock方法却返回null。原因是mock设置时的either上下文与ServiceOne内部的either上下文不是同一个实例,导致Mockito的参数匹配失败。
可行解决方案
方案1:调整Mockito的参数匹配规则
Mockito会将Kotlin的上下文接收器编译为方法的第一个隐式参数,因此需要显式匹配这个上下文参数,允许任意Raise实例触发mock返回值。
修改后的测试代码:
class ServiceOneTests { @Test fun `should return the correct aggregation result`() { val serviceTwo = mock(ServiceTwo::class.java) val serviceOne = ServiceOne(serviceTwo) // 用any()匹配任意Raise上下文实例,eq("1")匹配指定参数 `when`(serviceTwo.call(any<Raise<BusinessError>>(), eq("1"))).thenReturn("1") val result = either { val mockResult = serviceTwo.call("1") assertEquals("1", mockResult) serviceOne.call("1") } when(result) { is Either.Left -> fail() is Either.Right -> assertEquals("1", result.value) } } }
方案2:改用MockK(推荐)
MockK是Kotlin专用的Mock库,对上下文接收器、协程等Kotlin特性支持更原生,无需处理编译后的参数转换逻辑。
- 先添加MockK依赖(以Gradle为例):
testImplementation "io.mockk:mockk:1.13.8"
- 修改后的测试代码:
import io.mockk.every import io.mockk.mockk import org.junit.Test import kotlin.test.assertEquals import kotlin.test.fail class ServiceOneTests { @Test fun `should return the correct aggregation result`() { val serviceTwo = mockk<ServiceTwo>() val serviceOne = ServiceOne(serviceTwo) // 直接匹配上下文接收器的调用场景 every { with(any<Raise<BusinessError>>()) { serviceTwo.call("1") } } returns "1" val result = either { val mockResult = serviceTwo.call("1") assertEquals("1", mockResult) serviceOne.call("1") } when(result) { is Either.Left -> fail() is Either.Right -> assertEquals("1", result.value) } } }
内容的提问来源于stack exchange,提问作者codependent
相关产品推荐
相关产品推荐

