wuujcik
wuujcik

Reputation: 66

How to test SnapshotStateList being updated

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

Answers (1)

tyg
tyg

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

Related Questions