我希望能够对具有延迟发射的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)
}
答案 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)