Unit Testing Lifecycle and State in ViewModels
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 change.
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. It’s available from 2.9.0-alpha08:
implementation("androidx.lifecycle:lifecycle-viewmodel-testing:{version}")
Next, define your ViewModel:
class MyViewModel(
scope: CoroutineScope,
val handle: SavedStateHandle,
) : ViewModel(scope) { … }
/* Class used by SavedStateHandle. */
@Parcelize
data class MyData(
val name: String,
val surname: String,
) : Parcelable
Finally, 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 parcelizing).
it.recreate()
// Verify state is restored correctly after parcelizing.
assertThat(it.viewModel.handle["key"])
.isEqualTo(MyData("John", "Doe"))
}
}
}
Test in Details
- ViewModelScenario.recreate() simulates Android’s state saving and restoring, including parcelizing (see Save UI states).
- It ensures that data in SavedStateHandle is correctly saved and restored.
- AutoCloseable
use {}
ensures ViewModelStore.clear() / ViewModel.onCleared() runs after the block finishes. - You can manually call ViewModelScenario.close() to trigger a clearing.
- Also, ViewModelScenario is KMP compatible.
We invite you to try out the new API and share any issues or feedback through our Lifecycle issue tracker.
Happy testing!
The code snippets in this blog have the following license:
// Copyright 2024 Google LLC. SPDX-License-Identifier: Apache-2.0