Description
Right now it is possible to create and access dependencies in UI tests via EntryPoints for pretty much every component. If one needs a dependency from ActivityRetainedComponent
, an EntryPoint
targeting ActivityComponent
and FragmentComponent
does the trick, because both components inherit the dependencies from ActivityRetainedComponent
(and SingletonComponent
, which however can be injected directly in the @HiltAndroidTest
class).
Where this falls short is when one tries to access ViewModelComponent
. Reason for this is because reference of the generated component in HiltViewModelFactory
is never stored anywhere, so it becomes invisible to the outside world.
I understand that to let this work with the same mechanism like Fragments and Activitys, Hilt would have to generate a custom base instance of the ViewModel
implementation and let this implement GeneratedComponentManager<ViewModelComponent>
. Why hasn't this taken into consideration? Shouldn't the class that shares the lifetime with the component being able to hold an instance of it?
Right now, the only workaround is to make dependencies test-accessible in your ViewModel
and let your test grab the original ViewModel
instance from the factory:
@HiltViewModel
internal class MyViewModel @Inject constructor(
@VisibleForTesting internal val stateHandle: SavedStateHandle
) : CustomBaseViewModel<Foo>() { ... }
// ...
private val viewModel: MyViewModel by lazy {
var viewModel: MyViewModel? = null
fragmentRule.fragmentScenario?.onFragment { fragment ->
viewModel = ViewModelProvider(fragment)[MyViewModel::class.java]
}
requireNotNull(viewModel) { "Fragment is not yet initialized" }
}
@Test
fun myTest() {
fragmentRule.launch()
// do stubbing / verification
viewModel.stateHandle.get(...)
}