【问题标题】:Testing Observable Field Changes within a Coroutine在协程中测试可观察的字段变化
【发布时间】:2020-02-06 15:19:41
【问题描述】:

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

方法如下:

 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. 
        }
    }

顺便说一句,isProgressObservableBoolean

【问题讨论】:

    标签: android unit-testing kotlin kotlin-coroutines


    【解决方案1】:

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

    1. isProcesscheckoutInteractor 的模拟或间谍传递到您的班级。
    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)
        }
    }
    

    【讨论】:

    • checkoutInteractor 已经是一个 mock,isProgress 是 viewmodel 中的一个字段,将它带到构造函数级别是没有意义的,因为它是 20 个字段之一。但我不知道有 inOrder api。我试试看
    • 也许可以帮助其他人,我没有将我的字段传递给构造函数我只是像这样刺伤它when(viewModel.isProgress).thenReturn(mock(ObservableBoolean::class.java) ) ,视图模型已经是一个间谍
    • @Rainmaker 1. 我的例子是——嗯——一个例子,所以你可以随意传递变量和字段。 2. 注意不要在测试中模拟太多。将间谍活动视为有效选项,以及虚拟对象(存根)。
    猜你喜欢
    • 2017-12-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-03-11
    • 1970-01-01
    • 1970-01-01
    • 2017-09-07
    • 2021-10-02
    相关资源
    最近更新 更多