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

如何测试CompletableEmitter.tryOnError()?附相关实现代码

如何测试CompletableEmitter.tryOnError()方法?

首先得先把你代码里的catch块补全,让tryOnError()真正发挥作用,同时别忘了执行传入的finally逻辑——毕竟你的函数设计里有这个参数:

inline fun completable(crossinline action: () -> Unit) = completable(action, {})
inline fun completable(
    crossinline action: () -> Unit,
    crossinline finally: () -> Unit
): Completable {
    return Completable.create { emitter ->
        try {
            action()
            emitter.onComplete()
        } catch (t: Throwable) {
            // 这里补上tryOnError的调用
            emitter.tryOnError(t)
        } finally {
            // 执行传入的finally逻辑
            finally()
        }
    }
}

接下来,我们用RxJava自带的TestObserver来测试tryOnError()的核心行为——它只会在**下游订阅者仍处于活跃状态(未取消、未完成、未发生错误)**时发送错误并返回true,否则返回false且不会发送错误。

场景1:下游活跃时,tryOnError成功发送错误

这个场景验证正常情况下,异常被正确传递到下游:

import io.reactivex.rxjava3.core.Completable
import io.reactivex.rxjava3.observers.TestObserver
import org.junit.Test
import kotlin.test.assert

class CompletableTest {

    @Test
    fun `when action throws exception and downstream is active, tryOnError sends error`() {
        val testException = RuntimeException("Expected test error")
        var finallyExecuted = false

        // 创建我们的Completable,action抛出异常,finally标记执行状态
        val testCompletable = completable(
            action = { throw testException },
            finally = { finallyExecuted = true }
        )

        // 用TestObserver订阅
        val testObserver = testCompletable.test()

        // 验证:收到了预期的异常,finally被执行
        testObserver.assertError(testException)
        assert(finallyExecuted)
    }
}

场景2:下游已取消时,tryOnError不会发送错误

这个场景要模拟下游已经取消订阅的情况,验证tryOnError()返回false且错误不会被传递:

@Test
fun `when downstream is cancelled, tryOnError returns false and does not send error`() {
    val testException = RuntimeException("Should not be sent")
    var tryOnErrorResult = false
    var finallyExecuted = false

    // 直接创建Completable模拟下游取消的场景
    val testCompletable = Completable.create { emitter ->
        // 先手动取消emitter,模拟下游已经取消订阅
        emitter.dispose()
        try {
            throw testException
        } catch (t: Throwable) {
            // 记录tryOnError的返回结果
            tryOnErrorResult = emitter.tryOnError(t)
        } finally {
            finallyExecuted = true
        }
    }

    val testObserver = testCompletable.test()

    // 验证:tryOnError返回false,下游没有收到错误,finally被执行
    assert(!tryOnErrorResult)
    testObserver.assertNoErrors()
    testObserver.assertNotComplete()
    assert(finallyExecuted)
}

补充:用TestObserver.cancel()模拟下游取消

如果你想更贴合自己的completable()函数测试下游取消场景,也可以通过TestObserver的cancel()方法提前取消订阅:

@Test
fun `when test observer cancels before exception, tryOnError does nothing`() {
    val testException = RuntimeException("Should not reach observer")
    var tryOnErrorResult = false
    var finallyExecuted = false

    val testCompletable = Completable.create { emitter ->
        try {
            // 等待一下,方便下游先取消订阅
            Thread.sleep(100)
            throw testException
        } catch (t: Throwable) {
            tryOnErrorResult = emitter.tryOnError(t)
        } finally {
            finallyExecuted = true
        }
    }

    val testObserver = testCompletable.test()
    // 立即取消订阅
    testObserver.cancel()

    // 等待异步操作完成
    Thread.sleep(200)

    assert(!tryOnErrorResult)
    testObserver.assertNoErrors()
    assert(finallyExecuted)
}

核心思路就是覆盖tryOnError()的两种核心分支:下游活跃和非活跃,用TestObserver来验证事件的发送情况,同时确保finally逻辑始终被执行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 08:04:26