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

RxJava与Retrofit单元测试代码覆盖率问题排查求助

解决RxJava Repository方法测试覆盖率不足的问题

看起来你遇到了RxJava单元测试的典型问题:你的测试只触发了Single.create那一行代码,完全没执行后面的API响应处理逻辑,导致覆盖率拉低。下面我来帮你分析原因,一步步解决问题:

核心问题所在

你的测试逻辑绕开了Repository层的核心处理!RxJava的Single是冷流——只有当有订阅者订阅它的时候,内部的创建逻辑才会执行。而你原测试里,调用mTokenRepository.resetPassword(MOCK_EMAIL)后,根本没订阅这个方法返回的Single,反而直接去订阅了mock的API接口方法,这等于跳过了Repository里的所有代码。

修正后的单元测试代码

你需要订阅Repository返回的Single,而不是直接操作mock的API。修改后的测试代码如下:

@Test
fun resetPassword_200() {
    // 1. Mock API接口返回成功响应
    val mockApiResponse = Response.success(200, sMockResetPasswordResponse)
    Mockito.`when`(mApiInterfacePanda.resetPassword(Mockito.anyString()))
        .thenReturn(Single.just(mockApiResponse))

    // 2. 调用Repository的方法,并直接订阅返回的Single(用test()方法更简洁)
    val testObserver = mTokenRepository.resetPassword(MOCK_EMAIL)
        .test()

    // 3. 执行断言
    testObserver.assertSubscribed()
    testObserver.assertComplete()
    // 注意:这里断言的是Repository返回的ResetPassword对象,不是API的Response
    testObserver.assertResult(sMockResetPasswordResponse)
}

额外优化建议

1. 简化Repository层代码

你当前用Single.create手动包裹的方式有点冗余,其实可以用RxJava的操作符链式调用简化,这样代码更清晰,也更容易测试:

fun resetPassword(email: String): Single<ResetPassword> {
    return mApiInterfacePanda.resetPassword(email)
        .subscribeOn(Schedulers.io())
        .observeOn(AndroidSchedulers.mainThread())
        .map { response ->
            when(response.code()) {
                200 -> response.body() ?: throw Exception("Empty response body")
                else -> throw Exception("Server Error")
            }
        }
        .doOnSubscribe { subscription ->
            mCompositeDisposable.add(subscription)
        }
}

2. 处理测试环境的线程调度问题

如果测试时遇到AndroidSchedulers.mainThread()报错(测试环境没有Android主线程),可以在测试类里设置RxJava的测试调度器:

@Before
fun setUp() {
    // 把主线程和IO线程都替换成当前线程执行
    RxAndroidPlugins.setMainThreadSchedulerHandler { Schedulers.trampoline() }
    RxJavaPlugins.setIoSchedulerHandler { Schedulers.trampoline() }
}

@After
fun tearDown() {
    // 测试结束后重置调度器,避免影响其他测试
    RxAndroidPlugins.reset()
    RxJavaPlugins.reset()
}

这样所有RxJava的调度都会在当前测试线程执行,不会出现异步等待的问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 18:27:57