在协程中测试可观察字段的变化

Testing Observable Field Changes within a Coroutine

我正在编写单元测试,当我在执行挂起函数之前和之后更改可观察值时,我遇到了这种特殊情况。我想编写一个单元测试来检查该值是否正确更改了两次。

方法如下:

 fun doSomething() {
            viewModelScope.launch(ioDispatcher) {
                try {
                    viewModelScope.launch(Dispatchers.Main) {
                        commandLiveData.value = Pair(CANCEL_TIMER, null)
                    }
                    isProgress.set(true) //need to test it was set to true in one test
                    checkoutInteractor.doSomethingElse().run {
                        handleResult(this)
                    }
                    isProgress.set(false) //need to test it was set to false here in another test
                } catch (ex: java.lang.Exception) {
                    handleHttpError(ex)
                    isProgress.set(false)
                }
            }
        }

编写测试时我正在调用 doSomething() 我不确定如何检测该值在 checkoutInteractor.doSomethingElse 调用之前设置为 true 并在调用之后设置为 false 。

这是我的测试

@Test
    fun `test doSomething enables progress`() {
        runBlockingTest {
            doReturn(Response()).`when`(checkoutInteractor). checkoutInteractor.doSomethingElse()
            viewModel.doSomething()
            assertTrue(viewModel.isProgress.get()) //fails obviously as the value was already set to false after the `doSomethingElse` was executed. 
        }
    }

顺便说一句,isProgress 是一个 ObservableBoolean

您需要模拟或监视 isProgresscheckoutInteractor 字段以记录和验证其方法的执行。

  1. isProcesscheckoutInteractor 的 mock 或 spy 传递到您的 class。
  2. 执行doSomething()
  3. 验证 inOrder set()doSomethingElse() 函数

示例:

@Test
fun `test doSomething enables progress`() {
    runBlockingTest {
        val checkoutInteractor = Mockito.spy(CheckoutInteractor())
        val isProcess = Mockito.spy(ObservableBoolean(true))
        val viewModel = ViewModel(isProcess, checkoutInteractor)

        viewModel.doSomething()

        val inOrder = inOrder(isProcess, checkoutInteractor)
        inOrder.verify(isProcess).set(true)
        inOrder.verify(checkoutInteractor).doSomethingElse()
        inOrder.verify(isProcess).set(false)
    }
}