使用MockK测试含flatMap的Kotlin方法 覆盖率不升如何解决
问题核心原因
你的测试能运行成功但覆盖率无变化,核心有3个问题:
- 未订阅返回的
Completable:RxJava的冷流只有在订阅时才会执行内部逻辑,你仅调用register方法拿到了流对象,内部的flatMap、参数构造、API调用等代码完全没有运行,自然不会有覆盖率数据 - Mock规则匹配错误:
- 实际业务代码中
registerBuilder.build仅接收2个入参(firebaseId、uniqueId),你写的匹配规则是4个any(),永远无法命中 - 实际业务代码调用的API方法是
registerPushes,你Mock的是register方法,匹配失败
- 实际业务代码中
- 未处理RxJava异步调度器:默认的io、ui调度器是异步实现,就算你订阅了流,也会出现测试提前结束、业务逻辑未执行完的问题
修正后的测试实现
首先需要将业务代码中注入的SchedulerProvider替换为测试用的实现,统一用TestScheduler控制时序,修正后的测试代码如下:
import io.reactivex.rxjava3.schedulers.TestScheduler import io.mockk.verify // 测试用调度器实现,替换正式环境的异步调度器 val testScheduler = TestScheduler() val testSchedulerProvider = object : SchedulerProvider { override fun io(): Scheduler = testScheduler override fun ui(): Scheduler = testScheduler } @Test fun `register 调用成功时返回完成事件`() { // 构造入参对象,无特殊逻辑可以直接用真实对象,不需要mock val requestRegisterPushes = RequestRegisterPushes() // 修正build方法的参数匹配规则,对应实际的2个入参 every { registerBuilder.build(any<String>(), any<String>()) } returns requestRegisterPushes // 修正API方法名,匹配业务代码实际调用的registerPushes every { apiServiceFactory.build().registerPushes(requestRegisterPushes) } returns Observable.just(SimpleResponse()) // 订阅返回的Completable,触发内部逻辑执行 val testObserver = userRepository.register("x7gbyb68837g78s", "XXX-XXX-XXX") .test() // 触发测试调度器中所有待执行的任务,让所有异步逻辑同步跑完 testScheduler.triggerActions() // 断言执行结果符合预期 testObserver.assertComplete() testObserver.assertNoErrors() // 验证依赖方法确实被调用,确认逻辑走通 verify(exactly = 1) { registerBuilder.build("x7gbyb68837g78s", "XXX-XXX-XXX") } verify(exactly = 1) { apiServiceFactory.build().registerPushes(requestRegisterPushes) } }
额外优化建议
- 补充异常场景测试:可以Mock API返回
Observable.error(RuntimeException("接口报错")),验证你的方法是否正确传递异常,覆盖异常分支进一步提升覆盖率 - 可以引入RxJava测试规则,比如
RxJavaSchedulerRule自动替换全局调度器,不需要每个测试都手动写调度器替换逻辑
内容的提问来源于stack exchange,提问作者Novus Ordo Seclorum
相关产品推荐
相关产品推荐

