Reputation: 66
I have
class MyViewModel(private val activitiesRepo: ActivitiesRepo) : ViewModel() {
val activities = mutableStateListOf<Activity>()
private var activitiesFlow =
activitiesRepo.getAllActivitiesFlow().shareInViewModel(viewModelScope)
fun initialize() {
fetchActivities()
collectActivities()
}
private fun fetchActivities() =
viewModelScope.launch {
activitiesRepo.fetchAllActivities()
}
private fun collectActivities() = viewModelScope.launch {
activitiesFlow.collectLatest { newActivities ->
[email protected]()
[email protected](newActivities)
}
}
}
and I would like to test that activities
state is updated with the data collected in collectActivities()
I tried many approaches, but activities
are always an empty snapshot state list.
Here is one example of what I tried:
class MyViewModelTest {
private val activitiesRepo: ActivitiesRepo = mockk(relaxed = true)
private lateinit var viewModel: MyViewModel
@Before
fun setUp() {
Dispatchers.setMain(testDispatcher)
viewModel = MyViewModel(activitiesRepo = activitiesRepo)
}
@Test
fun `initialize updates activities list`() = runTest {
val mockActivities = listOf(Activity(id = 1))
every { activitiesRepo.getAllActivitiesFlow() } returns flowOf(mockActivities)
// Launch the collection of activities in the ViewModel
viewModel.initialize()
advanceUntilIdle()
assertThat(viewModel.activities).containsExactlyElementsIn(mockActivities)
}
@AfterEach
fun tearDown() {
Dispatchers.resetMain()
}
}
Upvotes: 0
Views: 45
Reputation: 15763
This is one of the reasons why you shouldn't even use MutableState
in the view model in the first place: https://stackoverflow.com/a/74601657
If you cannot or don't want to switch out your MutableState
with a MutableStateFlow
you need to wrap all write access to the MutableState with Snapshot.withMutableSnapshot
so the Compose runtime is notified of the change, even when it was triggered from a non-composable context (like your test).
Upvotes: 0