Модульный тест: Observer onChanged должен вызываться дважды, а не один раз - PullRequest
1 голос
/ 26 апреля 2019

Почему я получаю разные результаты при модульном тестировании моей ViewModel?

Я получил два теста.Когда я запускаю каждый тест по отдельности, это нормально, но когда я запускаю все тесты подряд, я получаю сообщение об ошибке.Это ViewModel, которая меняет состояние каждый раз, когда я получаю возврат от API.Я ожидаю, что android.arch.lifecycle.Observer.onChanged будет вызван два раза, но он просто вызывается один раз для второго теста.Модульный тест работает нормально, когда я заменяю verify(view, times(2)).onChanged(arg.capture()) на verify(view, atLeastOnce()).onChanged(arg.capture()) при первом тесте.

UserViewModel:

class UserViewModel(
        private val leApi: LeApi
): ViewModel() {
    private val _states = MutableLiveData<ViewModelState>()
    val states: LiveData<ViewModelState>
        get() = _states

    fun getCurrentUser() {
        _states.value = LoadingState
        leApi.getCurrentUser()
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(
                        { user -> _states.value = UserConnected(user) },
                        { t -> _states.value = FailedState(t) }
                )
        }
    }
}

UserViewModelTest:

@RunWith(MockitoJUnitRunner::class)
class UserViewModelTest {

    lateinit var userViewModel: UserViewModel

    @Mock
    lateinit var view: Observer<ViewModelState>

    @Mock
    lateinit var leApi: LeApi

    @get:Rule
    val rule = InstantTaskExecutorRule()

    @Before
    fun setUp() {
        RxAndroidPlugins.setInitMainThreadSchedulerHandler { Schedulers.trampoline() }
        userViewModel = UserViewModel(leApi)
        userViewModel.states.observeForever(view)
    }

    @Test
    fun testGetCurrentUser() {
        val user = Mockito.mock(User::class.java)
        `when`(leApi.getCurrentUser()).thenReturn(Single.just(user))
        userViewModel.getCurrentUser()

        val arg = ArgumentCaptor.forClass(ViewModelState::class.java)
        verify(view, times(2)).onChanged(arg.capture())

        val values = arg.allValues

        assertEquals(2, values.size)
        assertEquals(LoadingState, values[0])
        assertEquals(UserConnected(user), values[1])
    }

    @Test
    fun testGetCurrentUserFailed() {
        val error = Throwable("Got error")
        `when`(leApi.getCurrentUser()).thenReturn(Single.error(error))
        userViewModel.getCurrentUser()

        val arg = ArgumentCaptor.forClass(ViewModelState::class.java)
        verify(view, times(2)).onChanged(arg.capture()) // Error occurred here. That's the 70th line from stack trace.

        val values = arg.allValues
        assertEquals(2, values.size)
        assertEquals(LoadingState, values[0])
        assertEquals(FailedState(error), values[1])
    }
}

Ожидается: всеиспытания пройдены.

Фактические данные:

org.mockito.exceptions.verification.TooLittleActualInvocations: 
view.onChanged(<Capturing argument>);
Wanted 2 times:
-> at com.dev.titi.toto.mvvm.UserViewModelTest.testGetCurrentUserFailed(UserViewModelTest.kt:70)
But was 1 time:
-> at android.arch.lifecycle.LiveData.considerNotify(LiveData.java:109)
...