MutableStateFlow not getting updated while unit testing

39 Views Asked by At

I am trying to unit test a ViewModel where I am updating the value of a MutableStateFlow, but the thing is that when I try to test the Success State it gives me an error because the State remains as Idle, which is the initialization value. I am using Turbine to get the values since it is recommended, here my code

ViewModel code:

class HomeScreenViewModel  @Inject constructor(private val getUserByPersonaNameUseCase: GetUserByPersonaNameUseCase) :
    ViewModel() {

    private var _state = MutableStateFlow<State>(State.Idle)
    val state = _state

    suspend fun getUserByName(name: String, event: Event) = viewModelScope.launch {
        when (event) {
            Event.SearchPlayerByPersonaName -> {
                val result = getUserByPersonaNameUseCase.getUsersByPersonaName(name)

                _state.value = if (result.isNotEmpty()) {
                    State.Success(result)
                } else {
                    State.Error("Something went wrong")
                }
            }
        }
    }
}

ViewModelTest code:

@ExperimentalCoroutinesApi
class HomeScreenViewModelTest {
    
    lateinit var sut: HomeScreenViewModel
    lateinit var getUserByPersonaNameUseCase: GetUserByPersonaNameUseCase

    val fakeList = listOf(
        PlayerByPersonaName("player1", 1),
        PlayerByPersonaName("player2", 2),
        PlayerByPersonaName("player3", 3)
    )

    @Before
    fun setUp() {
        getUserByPersonaNameUseCase = mockk<GetUserByPersonaNameUseCase>()
        sut = HomeScreenViewModel(getUserByPersonaNameUseCase)
    }

    @Test
    fun `Given that getUserName is called with a name and the event is SearchPlayerByName, then the state is success `() =
        runBlocking {

            Dispatchers.setMain(Dispatchers.IO)

            //Given
            coEvery { getUserByPersonaNameUseCase.getUsersByPersonaName("atila") } returns fakeList

            sut.state.test {
                //When
                sut.getUserByName("atila", Event.SearchPlayerByPersonaName)
                //Then
                val result = awaitItem()

                assertTrue(result is State.Success)
            }

        }
}
1

There are 1 best solutions below

0
talhatek On

Make sure that you call getUserByPersonaNameUseCase by :

coVerify { getUserByPersonaNameUseCase.getUsersByPersonaName("atila") }

You not calling it correctly since you not using the TestDispatcher.

Make sure that you pass the Dispatchers.IO to viewModelScope :

    suspend fun getUserByName(name: String, event: Event) = viewModelScope.launch(Dispatchers.IO) {
         when (event) {
            Event.SearchPlayerByPersonaName -> {
               val result = getUserByPersonaNameUseCase.getUsersByPersonaName(name)

               _state.value = if (result.isNotEmpty()) {
                State.Success(result)
            } else {
                State.Error("Something went wrong")
            }
        }
    }
}