ArgumentCaptor vs InOrder来validation后续的回调与不同的参数

我正在测试使用Architecture ComponentsRoom库生成的DAO类。 我想检查加入多个表的查询返回的LiveData是否会在数据更改时更新。

我开始使用InOrdervalidation,但是发现无论我想expression什么论点,Mockito都会说这个方法是用另一个方法调用的(当我把这个断言改为那个时,它会说是另一个) 。

使用一个ArgumentCaptor原来是为了这个目的而正常工作,这是这个问题的主题:

为什么ArgumentCaptorvalidation在这里工作,但InOrder不?

看问题的答案如何validation多个方法调用与不同的参数 ,这两种方法应该工作正常。

下面是我的测试的简化版本,展示了这个问题:

 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() 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>>() val liveData = MutableLiveData<List>() // when liveData.observeForever(observer) liveData.value = firstList liveData.value = secondList liveData.value = thirdList liveData.value = lastList // then argumentCaptor<List>().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>>() val liveData = MutableLiveData<List>() // 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 { fun onChanged(value: T?) } class MutableLiveData { var value: T get() = _value set(value) { observers.forEach { it.onChanged(value) } _value = value } private lateinit var _value: T private var observers = mutableSetOf<Observer>() fun observeForever(observer: Observer) { if (::_value.isInitialized) observer.onChanged(_value) observers.add(observer) } } 

using argument captor传递,但using in order失败,并显示一条消息:

 java.lang.AssertionError: Expected :[] Actual :[Language(name=Java)] 

TL; DR-在Mockito-Kotlin的部分,这似乎是一个错误和/或错误的文档,就其checkfunction而言。

Mockito-Kotlin的维基说 :

如果你想对收到的参数做更多的断言,你可以使用check 。 […]如果你想让你的测试在一个check调用失败,你应该确保身体抛出一个错误[…]

check的实现调用Mockito的argThat ,并将提供的谓词作为parameter passing。 但是, ArgumentMatcher的文档指出 :

如果参数不匹配,该方法不应该断言。 它只应该返回false

因此,Mockito-Kotlin的文件与这个约束直接相矛盾。

我不知道如何解决这个问题,但你可以避免现在完全check ,并直接使用argThat (适当返回false ,而不是抛出)。

使用check (而不是由Mockito-Kotlin提供的)这样的function似乎工作正常:

 inline fun  check(noinline predicate: (T?) -> Unit): T? { return Mockito.argThat { try { predicate(it) true } catch (e: Throwable) { false } } }