Lifecycle 2.9.0-alpha01 introduced ViewModelScenario, a helper that simplifies unit testing for ViewModels.
Why It Matters
You can test a ViewModel
by simply creating an instance using its constructor in your test code. However, this approach has limitations — there is no straightforward way to:
- Trigger
ViewModelStore.clear()
/ViewModel.onCleared()
. - Simulate a save and restore instance state.
With ViewModelScenario
, these are now easy to test, helping you catch errors related to ViewModel
clean-up and saved state.
How to Use
First, add the dependency to your Gradle file:
implementation("androidx.lifecycle:lifecycle-viewmodel-testing:2.9.0-alpha10")
Next, define your ViewModel
:
class MyViewModel(
scope: CoroutineScope,
val handle: SavedStateHandle,
) : ViewModel(scope) {
// collapsed for simplicity
}
@Parcelize
data class MyData(
val name: String,
val surname: String,
) : Parcelable
Now, write a unit test for your ViewModel
using a ViewModelScenario
:
class MyViewModelTest {
@Test
fun testStateRestoration() = runTest { // this: TestScope
viewModelScenario { // this: CreationExtras
MyViewModel(
scope = this@runTest,
handle = createSavedStateHandle(),
)
}.use { it: ViewModelScenario ->
// Set a ViewModel state.
it.viewModel.handle["key"] = MyData("John", "Doe")
// Recreate ViewModel, simulating a state restoration (including parcelize).
it.recreate()
// Verify state is restored correctly after parcelize.
assertThat(it.viewModel.handle["key"]).isEqualTo(MyData("John", "Doe"))
}
}
}
Test in Details
ViewModelScenario.recreate()
simulates Android’s state saving and restoring, including parceling (see Save UI states).- It ensures that data in
SavedStateHandle
is correctly saved and restored.
- It ensures that data in
AutoCloseable.use {}
ensuresViewModelStore.clear()
/ViewModel.onCleared()
runs after theuse
block finishes.- You can manually call
ViewModelScenario.close()
to trigger a clearing.
- You can manually call
- Also,
ViewModelScenario
is KMP compatible.
ℹ️ If you enjoyed the article you might enjoy following me on Bluesky. ℹ️