微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

单元测试 RxJava repeatWhen 操作符总是卡在第一次迭代

如何解决单元测试 RxJava repeatWhen 操作符总是卡在第一次迭代

我正在尝试对我的视图模型代码进行单元测试,该代码执行服务器轮询以在其 Status == ELIGIBLE 后立即返回数据

我的问题是,它总是在加载(重复)时断言,而不是等待调用 onSuccess 来断言正确的状态。

我已经放置了一些日志来跟踪正在发生的事情:

doOnSubscribe called
repeatWhen called
doOnNext called
takeuntil called
doOnNext called
takeuntil called

如您所见,repeatWhentakeuntil调用了两次(这是预期的),但之后没有调用 onSuccess

最终测试失败并显示此消息 Caused by: java.lang.AssertionError: expected:<SUCCESS> but was:<LOADING>

如果我删除了失败的行,下一个断言也会失败并显示消息:

java.lang.AssertionError: 
Expected :ELIGIBLE
Actual   :null

这意味着尚未到达 onSuccess 方法,并且仍在加载。

我也不喜欢使用 Schedulers.trampoline() .. 它有效,但它会同步等待 5 秒。我更喜欢用 TestScheduler.advanceByTime() 代替。

这是客户端代码

fun startStatusPolling() {
    val pollingSingle = shiftPayService.obtainCardStatus()
            .repeatWhen {
                println("repeatWhen called")
                //POLLING_INTERVAL_SECONDS = 5
                it.delay(POLLING_INTERVAL_SECONDS,TimeUnit.SECONDS)
            }
            .takeuntil { item ->
                println("takeuntil called")
                item.cardStatus != Status.PENDING
            }.doOnNext {
                println("doOnNext called")
            }
            .lastElement()
            .toSingle()

    subscribe(pollingSingle,pollingStatusLiveData)
}

还有我的测试课:

@RunWith(HomebaseRobolectricTestRunner::class)
@LooperMode(LooperMode.Mode.PAUSED)
class CardviewmodelTest {

    lateinit var viewmodel: Cardviewmodel
    var testScheduler = TestScheduler()

    @Before
    fun setup() {
        RxJavaPlugins.setcomputationSchedulerHandler { testScheduler }
        RxJavaPlugins.setIoSchedulerHandler { testScheduler }
        RxAndroidplugins.setinitMainThreadSchedulerHandler { testScheduler }

        val cardStatusPending: CardStatus = mockk(relaxed = true) {
            every { status } returns Status.PENDING
        }

        val cardStatusEligible: CardStatus = mockk(relaxed = true) {
            every { status } returns Status.ELIGIBLE
        }

        val cardService: CardService = spyk {
            every { obtainCardStatus() } returnsMany listof(
                    Single.just(cardStatusPending),Single.just(cardStatusEligible)
            )
        }

        viewmodel = Cardviewmodel(cardService)
    }

    @Test
    fun testCardStatusPolling() {
        viewmodel.startStatusPolling()
        shadowOf(Looper.getMainLooper()).idle()

        testScheduler.advanceTimeBy(5,TimeUnit.SECONDS)

        //after 5 sec delay,single is resubscibed,returning the second single cardStatusEligible
        assertEquals(Result.Status.SUCCESS,viewmodel.pollingStatusLiveData.value?.status)
        assertEquals(EligiblityStatus.ELIGIBLE,viewmodel.pollingStatusLiveData.value?.data?.eligibilityStatus)

    }
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。