【问题标题】:RxJava observable completed but doOnComplete callback not triggered in unit testRxJava observable 已完成,但在单元测试中未触发 doOnComplete 回调
【发布时间】:2019-01-02 13:17:25
【问题描述】:

我有以下逻辑用于从可完成(使用doOnComplete 回调)创建可观察数据,这是经过单元测试的:

class ObservableSrc(val completableSrc: CompletableSrc) {

    fun getObservable(client: Client): Observable<State> {
        return client.getResults()
            .concatMap { processResult(client, it.values) }
    }

    private fun processResult(Client: Client, values: Values): Observable<State> =
        completableSrc.getCompletable(client.type, values)
            .doOnComplete { client.doSomething(values)}
            .toSingleDefault(…)
            .map { … }
            .toObservable()
            .startWith(State.InProgress)
}

@Test
fun test() {
    whenever(client.type).doReturn(Type.SOME_TYPE)
    whenever(client.getResults()).doReturn(Observable.just<Result>(Result(mock())))
    whenever(completableSrc.getCompletable(any(), any())).doReturn(Completable.complete())
    doNothing().whenever(client).doSomething(any())

    val observer = tested.getObservable(client).test()

    observer.assertComplete()
    verify(completableSrc, times(1)).getCompletable(any(), any())
    verify(client, times(1)).doSomething(any())
}

问题是验证 doSomething 给出了与模拟 client 的 2 次交互,但未调用所需的方法。我发现如果我像这样改变链接:

completableSrc.getCompletable(client.type, values)
                .toSingleDefault(…)
                .map { … }
                .doOnSuccess { client.doSomething(values)}
                .toObservable()
                .startWith(State.InProgress)

然后就可以了。我只是不知道为什么带有doOnComplete 的先前版本失败(observer.assertComplete() 执行成功)。似乎它被处理得太早了,所以没有调用回调,但为什么呢?

【问题讨论】:

  • Completable 是否应该在任何这些链式方法调用中达到完成阶段?
  • startWith 来自哪里?据我所知,您正在将Completable 转换为Single.toSingleDefault(…)),但Single 没有startWith(因为它确实有意义,因为它只发出一个值)
  • 我的错,startWith 来自调用 toObservable 后的 observable。我更新了问题。 Completable 是一个网络调用(Retrofit with Rx),但它在单元测试中被模拟了。

标签: unit-testing junit kotlin mockito rx-java2


【解决方案1】:

更新

使用单元测试和模拟测试代码。我根据个人喜好使用 kolin.testmockk

interface CompletableSrc {
    fun getCompletable(): Completable
}

interface Client {
    fun doSomething()
    fun doSomethingElse()
}

class CompletableTest {

    @Test
    fun `functions doOnComplete and doOnSuccess should work as expected`() {
        val completableSrc: CompletableSrc = mockk {
            every { getCompletable() } returns Completable.complete()
        }

        val client: Client = mockk {
            every { doSomething() } returns Unit
            every { doSomethingElse() } returns Unit
        }

        val observable = completableSrc.getCompletable()
            .doOnComplete { client.doSomething() }
            .toSingleDefault(0)
            .map { it + 1 }
            .doOnSuccess { client.doSomethingElse() }
            .toObservable()
            .startWith(-1)

        val test = observable.test()
        test.assertComplete()
        test.assertValues(-1, 1)

        verify(exactly = 1) {
            completableSrc.getCompletable()
            client.doSomething()
            client.doSomethingElse()
        }
    }
}

如您所见,断言和模拟验证均成功。

上一个

您的代码应该可以正常工作,因为我无法运行它,所以我真的很难分辨出哪里出了问题,但是我创建了一个 sn-p,它做的事情几乎相同,并且可以按预期工作。

示例

fun main(args: Array<String>) {
    var sideEffect = 0

    val observable = Completable.complete()
        .doOnComplete { sideEffect += 1 }
        .toSingleDefault(sideEffect)
        .map { sideEffect + 1 }
        .doOnSuccess(::println)
        .toObservable()
        .startWith(-1)

    val test = observable.test()
    test.assertComplete()
    test.assertValues(-1, 2)
}

输出

2

执行两个副作用函数Completable.doOnCompleteSingle.doOnSuccess,更新变量sideEffect 并打印到控制台。

【讨论】:

  • 你是对的,代码在应用程序中运行良好。你试过用 JUnit 运行它吗?
  • 所以在你的例子中 assertCompleteverify 是成功的。我的只有assertComplete。你可以模拟doSomething 对交互不做任何事情并查看结果吗?我会试着环顾一下我的模拟 - 也许它们有问题。
  • @Luke 实际上它是被嘲笑的 (every { doSomething() } returns Unit),否则它会抛出异常
  • 我知道。我的意思是使用完全“什么都不做”的模拟(就像在我的代码中一样)。我正在尝试在您的代码中反映我的代码,但我几乎没有想法。
猜你喜欢
  • 1970-01-01
  • 2020-08-12
  • 2015-10-28
  • 2021-07-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-22
相关资源
最近更新 更多