单元测试RxJava + Retrofit调用方法内部

时间:2018-02-09 13:33:28

标签: android unit-testing mockito retrofit2 rx-java2

我想测试的方法包含对改装服务的两次调用:

cleartool mklabel MY_LABEL TestFile.txt@@\main\1

internal fun poll(): Completable { return presenceService.askForFrequency(true).toObservable() .flatMap { it -> Observable.interval(it.frequency, TimeUnit.SECONDS, Schedulers.io()) } .flatMapCompletable { _ -> presenceService.sendHeartbeat() } .subscribeOn(Schedulers.io()) .retry() } 是在课程中注入的,所以我提供了一个模拟的测试:

presenceService

检查调用val frequency = PublishSubject.create<Presence>() val heartbeat = PublishSubject.create<Unit>() val mockPresenceService = mock<PresenceService> { on { askForFrequency(any()) } doReturn frequency on { sendHeartbeat() } doReturn heartbeat } 方法的测试是否正常,但是检查轮询请求发送的测试从不起作用:

askForFrequency

单元测试运行的日志是:

@Test
fun presenceService_sentHeartbeat() {
    RxJavaPlugins.setIoSchedulerHandler { scheduler }

    frequency.onNext(Presence(1)) //polls with 1s interval
    heartbeat.onNext(Unit)
    presenceMaintainer.onActivityResumed(any())
    scheduler.advanceTimeBy(2, TimeUnit.SECONDS)
    verify(mockPresenceService).askForFrequency(true) //works correctly
    verify(mockPresenceService).sendHeartbeat() //never works
}

问题是:如何测试第二种方法(Wanted but not invoked: presenceService.sendHeartbeat(); However, there was exactly 1 interaction with this mock: presenceService.askForFrequency(true); )也被调用(可能多次)

同时我发现问题在于第二个flatmap,因为此方法的测试正常工作(验证该方法被调用了60次):

sendHeartbeat

但是当我将调用的顺序更改为 internal fun pollTest(): Observable<Presence> { return Observable.interval(1, TimeUnit.SECONDS, Schedulers.io()) .subscribeOn(Schedulers.io()) .flatMap { it -> presenceService.askForFrequency(true).toObservable() } } @Test fun presenceService_sentHeartbeat() { frequency.onNext(Presence(1)) val result = arrayListOf<Unit>() presenceMaintainer.pollTest().subscribe({ t -> result.add(Unit) }) Thread.sleep(60*1000) println(result.size) verify(mockPresenceService, Times(60)).askForFrequency(true) } 时,测试停止工作,并且只调用一次mock。

1 个答案:

答案 0 :(得分:1)

默认情况下,Observable.interval()在计算调度程序上运行,而不在io调度程序上运行。这意味着,2秒等待将实时运行,因此您的测试将在调用sendHeartBeat()之前完成2秒。