我测试使用生成的我DAO类Room从库Architecture Components。我想检查LiveData连接多个表的查询返回的数据是否会在数据更改时更新。
我从使用InOrder验证开始,但发现无论我想断言什么参数,Mockito 都会说该方法是用不同的方法调用的(当我将断言更改为那个时,它会说是另一个)。
使用ArgumentCaptor结果证明可以很好地用于此目的,这是这个问题的主题:
ArgumentCaptor验证在这里起作用,但InOrder不起作用?查看有关如何使用不同 params 验证多个方法调用的问题的答案,这两种方法都应该可以正常工作。
这是我的测试的简化版本,展示了这个问题:
package com.example
import com.nhaarman.mockito_kotlin.argumentCaptor
import com.nhaarman.mockito_kotlin.check
import com.nhaarman.mockito_kotlin.mock
import org.junit.Assert.assertEquals
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.Mockito.*
import org.mockito.junit.MockitoJUnitRunner
@Suppress("IllegalIdentifier")
@RunWith(MockitoJUnitRunner::class)
class MultipleCallbacksVanillaTest {
private val java = Language("Java")
private val javascript = Language("JavaScript")
private val kotlin = Language("Kotlin")
private val firstList = emptyList<Language>()
private val secondList = listOf(java)
private val thirdList = listOf(java, javascript, kotlin)
private val lastList = listOf(java, kotlin)
@Test fun `using argument captor`() {
// given
val observer = mock<Observer<List<Language>>>()
val liveData = MutableLiveData<List<Language>>()
// when
liveData.observeForever(observer)
liveData.value = firstList
liveData.value = secondList
liveData.value = thirdList
liveData.value = lastList
// then
argumentCaptor<List<Language>>().run {
verify(observer, times(4)).onChanged(capture())
val (firstValue, secondValue, thirdValue, lastValue) = allValues
assertEquals(firstList, firstValue)
assertEquals(secondList, secondValue)
assertEquals(thirdList, thirdValue)
assertEquals(lastList, lastValue)
}
}
@Test fun `using in order`() {
// given
val observer = mock<Observer<List<Language>>>()
val liveData = MutableLiveData<List<Language>>()
// when
liveData.observeForever(observer)
liveData.value = firstList
liveData.value = secondList
liveData.value = thirdList
liveData.value = lastList
// then
inOrder(observer).run {
verify(observer).onChanged(check { assertEquals(firstList, it) })
verify(observer).onChanged(check { assertEquals(secondList, it) })
verify(observer).onChanged(check { assertEquals(thirdList, it) })
verify(observer).onChanged(check { assertEquals(lastList, it) })
}
verifyNoMoreInteractions(observer)
}
}
data class Language(val name: String)
interface Observer<in T> {
fun onChanged(value: T?)
}
class MutableLiveData<T : Any> {
var value: T
get() = _value
set(value) {
observers.forEach { it.onChanged(value) }
_value = value
}
private lateinit var _value: T
private var observers = mutableSetOf<Observer<T>>()
fun observeForever(observer: Observer<T>) {
if (::_value.isInitialized) observer.onChanged(_value)
observers.add(observer)
}
}
Run Code Online (Sandbox Code Playgroud)
using argument captor通过,但using in order失败并显示一条消息:
java.lang.AssertionError:
Expected :[]
Actual :[Language(name=Java)]
Run Code Online (Sandbox Code Playgroud)
TL;DR -就其功能而言,这似乎是Mockito-Kotlincheck方面的一个错误和/或糟糕的文档。
Mockito-Kotlin 的wiki 说道:
如果您想对收到的参数进行更多断言,可以使用
check. [...]如果您希望测试在调用内失败check,则应确保主体抛出错误[...]
的实现check 调用 Mockito 的argThat,并将提供的谓词作为参数传递。但是,文档说明ArgumentMatcher:
如果参数不匹配,该方法永远不应该断言。它应该只返回
false。
因此,Mockito-Kotlin 的文档与此约束直接矛盾。
我不知道如何解决这个问题,但你check现在可以完全避免,并argThat直接使用(适当返回false,而不是抛出)。
| 归档时间: |
|
| 查看次数: |
1653 次 |
| 最近记录: |