ArgumentCaptor vs InOrder to verify subsequent callbacks with different arguments

I was testing my DAO class generated using the Room library from Architecture Components. I wanted to check that the LiveData returned by a query joining multiple tables was going to be updated when data changes.

I started out by using InOrder verification, but found that whatever argument I wanted to assert, Mockito would say that the method was invoked with a different one (and when I changed the assertion to that one, it would say it was the other one).

Using an ArgumentCaptor turned out to work fine for this purpose, which is the subject of this question:

Why does ArgumentCaptor verification work here, but InOrder does not?

Looking at the answers to question on how to verify multiple method calls with different params, both methods should work fine.

Here’s a simplified version of my test that showcases the issue:

package com.example

import android.arch.core.executor.testing.InstantTaskExecutorRule
import android.arch.lifecycle.MutableLiveData
import android.arch.lifecycle.Observer
import com.google.common.truth.Truth.assertThat
import com.nhaarman.mockito_kotlin.*
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.junit.MockitoJUnitRunner

@Suppress("IllegalIdentifier")
@RunWith(MockitoJUnitRunner::class)
class MultipleCallbacksTest {

    @Rule
    @JvmField
    var instantTaskExecutorRule = InstantTaskExecutorRule()

    @Test fun `using argument captor`() {
        // given
        val observer: Observer<List<Language>> = mock()
        val liveData = MutableLiveData<List<Language>>()

        val java = Language("Java")
        val javascript = Language("JavaScript")
        val kotlin = Language("Kotlin")

        // when
        liveData.observeForever(observer)
        liveData.value = emptyList()
        liveData.value = listOf(java)
        liveData.value = listOf(java, javascript, kotlin)
        liveData.value = listOf(java, kotlin)

        // then
        argumentCaptor<List<Language>>().run {
            verify(observer, times(4)).onChanged(capture())
            assertThat(firstValue).isEmpty()
            assertThat(secondValue).containsExactly(java)
            assertThat(thirdValue).containsExactly(java, javascript, kotlin)
            assertThat(lastValue).containsExactly(java, kotlin)
        }
    }

    @Test fun `using in order`() {
        // given
        val observer: Observer<List<Language>> = mock()
        val liveData = MutableLiveData<List<Language>>()

        val java = Language("Java")
        val javascript = Language("JavaScript")
        val kotlin = Language("Kotlin")

        // when
        liveData.observeForever(observer)
        liveData.value = emptyList()
        liveData.value = listOf(java)
        liveData.value = listOf(java, javascript, kotlin)
        liveData.value = listOf(java, kotlin)

        // then
        inOrder(observer) {
            verify(observer).onChanged(check {
                assertThat(it).isEmpty()
            })
            verify(observer).onChanged(check {
                assertThat(it).containsExactly(java)
            })
            verify(observer).onChanged(check {
                assertThat(it).containsExactly(java, javascript, kotlin)
            })
            verify(observer).onChanged(check {
                assertThat(it).containsExactly(java, kotlin)
            })
        }
        verifyNoMoreInteractions(observer)
    }

    private data class Language(val name: String)
}

using argument captor passes, but using in order fails with a message:

Not true that <[Language(name=Java)]> is empty