Search code examples
androidunit-testingandroid-testingandroidxmutablelivedata

Why onChange result is "false" in test LiveData


It's first my post on stackoverflow and i'm beginer in kotlin, Lifecycle, need help with it. I lost 2 days with it and need help.

I have SplashViewModel class

class SplashViewModel @Inject constructor(
    private val configuration: IConfiguration,
    private val compositeDisposable: CompositeDisposable) : BaseViewModel(compositeDisposable), SplashContract.ViewModel{

override val isLoggedLiveData: MutableLiveData<Boolean> = MutableLiveData()

init {
    setLoginStatus()
}

override fun setLoginStatus(){
    isLoggedLiveData.postValue(configuration.isUserLoggedIn())
}}

SplashViewModelTest class

class SplashViewModelTest : BaseTest(){

@get:Rule
val testRule = InstantTaskExecutorRule()

@Mock
private lateinit var configuration: IConfiguration

@Mock
private lateinit var compositeDisposable: CompositeDisposable

@Mock
private lateinit var observer: Observer<Boolean>

private lateinit var viewModel: SplashContract.ViewModel

override fun setup() {
    super.setup()
    trampolineRxPlugin()
    viewModel = SplashViewModel(
            configuration,
            compositeDisposable
    )
}

override fun tearDown() {
    super.tearDown()
    verifyNoMoreInteractions(
            configuration,
            compositeDisposable
    )
}

@Test
fun `should change livedata status to true when viewmodel is initialize`() {
    val isLogged = true

    `when`(configuration.isUserLoggedIn()).thenReturn(isLogged)

    viewModel.isLoggedLiveData.observeForever(observer)

    verify(configuration, Mockito.times(1)).isUserLoggedIn()
    verify(observer).onChanged(isLogged)
}

When run this test result is error

Argument(s) are different! Wanted: observer.onChanged(true); -> at com.example.kotlinmvvm.feature.splash.viewModel.SplashViewModelTest.should check configuration user login status when getIsLoggedLiveData is called(SplashViewModelTest.kt:85)

Actual invocation has different arguments: observer.onChanged(false); -> at androidx.lifecycle.LiveData.considerNotify(LiveData.java:113)

Comparison Failure:

Expected :observer.onChanged(true);

Actual :observer.onChanged(false);

Who knows what's going on?


Solution

  • What I suspect is happening is that you're instantiating view model (in setup) prior to following being invoked (with isLogged = true)...which is causing code in init to be invoked...and at that point it will return false.

    `when`(configuration.isUserLoggedIn()).thenReturn(isLogged)
    

    Did you intend perhaps to explicitly call setLoginStatus in your test as well (after above line)?