2 years ago

#11290

test-img

dsantamaria

Unit test multiple LiveData values in a ViewModel init block

Consider the following code:

sealed interface State {
    object Loading : State
    data class Content(val someString: String) : State
}

class SomeViewModel(getSomeStringUseCase: GetSomeStringUseCase) : ViewModel() {

    private val _someString = MutableLiveData<State>()
    val someString: LiveData<State> = _someString

    init {
        _someString.value = State.Loading
        viewModelScope.launch {
            _someString.value = State.Content(getSomeStringUseCase())
        }
    }
}

In a unit test it's pretty simple to test and assert the last value emitted by someString, however, if I want to assert all values emitted it gets more complicated because I can't subscribe to someString before SomeViewModel is initialized and if I do the subscription right after the initialization it is too late and the values were already emitted:

class SomeViewModelTest {

    @MockK
    private lateinit var getSomeStringUseCase: GetSomeStringUseCase
    private lateinit var viewModel: SomeViewModel

    @Before
    fun setUp() {
        coEvery { getSomeStringUseCase() } returns "Some String!"
        viewModel = SomeViewModel(getSomeStringUseCase)
    }

    // This test fails
    @Test
    fun test() {
        val observer = mockk<Observer<State>>(relaxed = true)
        viewModel.someString.observeForever(observer)
        verifyOrder {
            observer.onChanged(State.Loading)
            observer.onChanged(State.Content("Some String!"))
        }
    }
}

android

unit-testing

kotlin

mockk

0 Answers

Your Answer

Accepted video resources