单元测试有延迟的Rxjava可观察量

时间:2017-11-14 23:28:45

标签: android unit-testing kotlin rx-java rx-java2

我希望能够对具有延迟发射的Observable进行单元测试,但实际上并没有等待延迟时间。有没有办法做到这一点?

我目前正在使用CountDownHatch来延迟断言,这样可以正常工作,但会增加测试运行时间。

示例:

val myObservable: PublishSubject<Boolean> = PublishSubject.create<Boolean>()
fun myObservable(): Observable<Boolean> = myObservable.delay(3, TimeUnit.SECONDS)

@Test
fun testMyObservable() {
    val testObservable = myObservable().test()
    myObservable.onNext(true)

    // val lock = CountDownLatch(1)
    // lock.await(3100, TimeUnit.MILLISECONDS)
    testObservable.assertValue(true)
}

3 个答案:

答案 0 :(得分:20)

感谢@ aaron-he的答案,我能够提出一个完整的解决方案。

它使用TestScheduler的组合来推进时间,并使用RxJavaPlugins来覆盖testScheduler的默认调度程序。这允许在不修改或需要传入myObservable()的情况下测试Scheduler函数。

@Before
fun setUp() = RxJavaPlugins.reset()

@After
fun tearDown() = RxJavaPlugins.reset()

@Test
fun testMyObservable() {
    val testScheduler = TestScheduler()
    RxJavaPlugins.setComputationSchedulerHandler { testScheduler }

    val testObservable = myObservable().test()
    myObservable.onNext(true)

    testScheduler.advanceTimeBy(2, TimeUnit.SECONDS)
    testObservable.assertEmpty()
    testScheduler.advanceTimeBy(2, TimeUnit.SECONDS)
    testObservable.assertValue(true)
}

答案 1 :(得分:6)

TestScheduler非常适合这一点。它有一个方便的方法advanceTimeBy(long, TimeUnit)允许您控制时间。 Observable.delay overload method需要Scheduler

因此,只需使用Scheduler.computation()函数中的默认myObservable,并使用TestScheduler进行单元测试。

答案 2 :(得分:1)

发现A的某些奇怪行为,需要一段时间才能订阅,例如测试失败:

PublishSubject

但是,如果我们在调用private val scheduler = TestScheduler() @Test fun publishSubjectFailedTest() { val callback: DelayCallback = mock() val myPublishSubject: PublishSubject<Boolean> = PublishSubject.create() myPublishSubject .delay(10, TimeUnit.SECONDS, scheduler) .subscribeOn(scheduler) .observeOn(scheduler) .subscribe( Consumer<Boolean> { callback.onCalldown() }, Consumer<Throwable> { }, Action { } ) myPublishSubject.onNext(true) scheduler.advanceTimeBy(20, TimeUnit.SECONDS) verify(callback, times(1)).onCalldown() } 之前添加时间scheduler,例如onNext 那么测试将成功:

scheduler.advanceTimeBy(1, TimeUnit.NANOSECONDS)