Test MutableSharedFlow with runTest

479 views Asked by At

I’m having some trouble to test some state changes in my viewModel using MutableSharedFlow. For example, I have this class

class SampleViewModel : ViewModel() {
    private val interactions = Channel<Any>()
    private val state = MutableSharedFlow<Any>(
        onBufferOverflow = BufferOverflow.DROP_LATEST,
        extraBufferCapacity = 1
    )

    init {
        viewModelScope.launch {
            interactions.receiveAsFlow().collect { action ->
                processAction(action)
            }
        }
    }

    fun flow() = state.asSharedFlow()

    fun handleActions(action: Any) {
        viewModelScope.launch {
            interactions.send(action)
        }
    }

    suspend fun processAction(action: Any) {
        state.emit("Show loading state")

       // process something...

        state.emit("Show success state")
    }
}

I'm trying to test it using this method (already using version 1.6.1):

@Test
    fun testHandleActions() = runTest {
        val emissions = mutableListOf<Any>()
        val job = launch(UnconfinedTestDispatcher(testScheduler)) {
            viewModel.flow().collect {
                emissions.add(it)
                }
        }
        viewModel.handleActions("")
        assertTrue(emissions[0] is String)
        assertTrue(emissions[1] is String)
        job.cancel()
    }

If I test the viewmodel.processAction() it works like a charm. But if I try to test handleActions() I only receive the first emission and then it throws an IndexOutOfBoundsException If I use the deprecated runBlockingTest, it works

@Test
    fun testHandleActionsWithRunBlockingTest() = runBlockingTest {
        val emissions = mutableListOf<Any>()
        val job = launch {
            viewModel.flow().toList(emissions)
        }
        viewModel.handleActions("")
        job.cancel()

        assertTrue(emissions[0] is String)
        assertTrue(emissions[1] is String)
    }

Did I miss something using runTest block?

0

There are 0 answers