MockK verifySequence因对象引用验证失败的解决方法咨询(带参数密封类场景)
解决带参数密封类的MockK verifySequence验证问题
这个问题我之前处理过,核心痛点就是MockK默认用对象引用做断言,但每次新建的密封类实例(比如NetworkResult.Loading())都是不同的对象,引用不相等,自然验证失败。下面给你三个实用的解决方案,按需选择:
方案1:使用MockK的match函数做类型/参数匹配
直接跳过引用匹配,用match传入判断逻辑,只要对象的类型和参数符合预期就通过验证。这是最灵活的方案,不用修改密封类结构:
verifySequence { // 验证第一个调用是Loading类型 stateObserver.onChanged(match { it is NetworkResult.Loading }) // 验证第二个调用是Success类型,且data等于预期的list stateObserver.onChanged(match { it is NetworkResult.Success && (it as NetworkResult.Success).data == list }) }
如果需要更严谨的类型检查(比如避免泛型擦除的影响),可以在lambda里加入泛型判断,或者用when表达式细化匹配逻辑。
方案2:将密封类子类改为data class
默认的Kotlin类用引用比较equals,但data class会自动生成基于属性的equals和hashCode方法,这样MockK会自动用值匹配代替引用匹配。只需要修改密封类的结构:
sealed class NetworkResult<T> { // 改成data class,自动实现值相等逻辑 data class Success<T>(val data: T) : NetworkResult<T>() data class Error<T>(val message: String) : NetworkResult<T>() // 无参数的data class也可以正常生成equals data class Loading<T> : NetworkResult<T>() }
之后你原来的验证代码就能直接生效了:
verifySequence { stateObserver.onChanged(NetworkResult.Loading()) stateObserver.onChanged(NetworkResult.Success(list)) }
方案3:用capturingSlot捕获所有调用后验证
如果需要对状态序列做更复杂的校验(比如统计次数、检查中间状态),可以用MockK的capturingSlot捕获所有调用的参数,之后手动检查顺序和内容:
// 定义一个槽,泛型要和你的状态类型一致 val stateSlot = slot<NetworkResult<List<YourDataType>>>() // 配置MockK,捕获所有onChanged的调用参数 every { stateObserver.onChanged(capture(stateSlot)) } answers {} // 执行你的业务逻辑(触发状态变化的代码) // 获取所有捕获到的状态 val capturedStates = stateSlot.captures // 验证顺序和内容 assertEquals(2, capturedStates.size) assertTrue("第一个状态应该是Loading", capturedStates[0] is NetworkResult.Loading) assertTrue("第二个状态应该是Success", capturedStates[1] is NetworkResult.Success) assertEquals("Success的data不符合预期", list, (capturedStates[1] as NetworkResult.Success).data)
这种方式适合复杂场景,比如需要验证多个状态的流转过程,或者需要对每个状态的参数做详细校验。
内容的提问来源于stack exchange,提问作者Leonardo Sibela
相关产品推荐
相关产品推荐

