How to test ViewModel + Flow

Viewed 40

I'm doing a small project to learn flow and the latest Android features, and I'm currently facing the viewModel's testing, which I don't know if I'm performing correctly. can you help me with it?

Currently, I am using a use case to call the repository which calls a remote data source that gets from an API service a list of strings.

I have created a State to control the values in the view model:

data class StringItemsState(
    val isLoading: Boolean = false,
    val items: List<String> = emptyList(),
    val error: String = ""
)

and the flow:

private val stringItemsState = StringtemsState()

private val _stateFlow = MutableStateFlow(stringItemsState)
val stateFlow = _stateFlow.asStateFlow()

and finally the method that performs all the logic in the viewModel:

fun fetchStringItems() {
    try {
        _stateFlow.value = stringItemsState.copy(isLoading = true)
        viewModelScope.launch(Dispatchers.IO) {
            val result = getStringItemsUseCase.execute()

            if (result.isEmpty()) {
                _stateFlow.value = stringItemsState
            } else {
                _stateFlow.value = stringItemsState.copy(items = result)
            }

        }
    } catch (e: Exception) {
        e.localizedMessage?.let {
            _stateFlow.value = stringItemsState.copy(error = it)
        }
    }
}

I am trying to perform the test following the What / Where / Then pattern, but the result is always an empty list and the assert verification always fails:

private val stringItems = listOf<String>("A", "B", "C")

    @Test
    fun `get string items - not empty`() = runBlocking {
        // What
        coEvery {
            useCase.execute()
        } returns stringItems

        // Where
        viewModel.fetchStringItems()

        // Then
        assert(viewModel.stateFlow.value.items == stringItems)
        coVerify(exactly = 1) { viewModel.fetchStringItems() }

    }

Can someone help me and tell me if I am doing it correctly? Thanks.

0 Answers
Related