android / android/architecture-samples
launchFragmentInHiltContainer doesn't work with navGraphViewModels
- Dominant language
- Kotlin
- Stars
- 45.8k
- Forks
- 11.9k
- PR merge metrics
- No merged PRs in 30d
Description
Hi,
For test purposes I've modified the code of `launchFragmentInHiltContainer` to this:
```kotlin
const val THEME_EXTRAS =
"androidx.fragment.app.testing.FragmentScenario.EmptyFragmentActivity.THEME_EXTRAS_BUNDLE_KEY"
inline fun launchFragmentInHiltContainer(
fragmentArgs: Bundle? = null,
@StyleRes themeResId: Int = R.style.FragmentScenarioEmptyFragmentActivityTheme,
navHostController: TestNavHostController? = null,
crossinline action: Fragment.() -> Unit = {}
) {
val componentName = ComponentName(
ApplicationProvider.getApplicationContext(),
HiltTestActivity::class.java
)
val intent = Intent
.makeMainActivity(componentName)
.putExtra(THEME_EXTRAS, themeResId)
launch(intent).onActivity { activity ->
val fragment = activity
.supportFragmentManager
.fragmentFactory
.instantiate(Preconditions.checkNotNull(T::class.java.classLoader), T::class.java.name)
.also { it.arguments = fragmentArgs }
fragment.viewLifecycleOwnerLiveData.observeForever {
if (it != null) {
navHostController?.let { controller ->
controller.setGraph(R.navigation.nav_graph)
controller.setCurrentDestination(R.id.tasks_fragment_dest)
Navigation.setViewNavController(fragment.requireView(), controller)
}
}
}
activity.supportFragmentManager
.beginTransaction()
.add(android.R.id.content, fragment, "")
.commitNow()
fragment.action()
}
}
```
Then I've updated test designated for redirecting user to `add_edit_task_fragment_dest`:
```kotlin
@Test
fun clickAddTaskButton_navigateToAddEditFragment() {
// GIVEN - On the home screen
val navController = TestNavHostController(ApplicationProvider.getApplicationContext())
navController.setViewModelStore(ViewModelStore())
launchFragmentInHiltContainer(Bundle(), R.style.AppTheme, navController)
// WHEN - Click on the "+" button
onView(withId(R.id.add_task_fab)).perform(click())
// THEN - Verify that we navigate to the add screen
assertEquals(navController.currentDestination?.id, id.add_edit_task_fragment_dest)
}
```
In `TaskFragment` changed only the line with propagating view model lazily but using `navGraphViewModels` instead of `viewModels` like this:
```kotlin
private val viewModel
by navGraphViewModels(R.id.nav_graph) { defaultViewModelProviderFactory }
```
The all tests consisting of navigation just fails:
`IllegalStateException: Fragment TasksFragment{fe2ac75} (8c347050-d52e-4da4-ad2d-e4694c0ceb0f id=0x1020002 tag=) does not have a NavController set`
Any workarounds?
Contributor guide
Research direction
Start with the launchFragmentInHiltContainer helper and the clickAddTaskButton_navigateToAddEditFragment navigation test, then inspect TaskFragment's navGraphViewModels setup. Run the navigation tests and compare the helper's NavController assignment with the fragment lifecycle. Done means the tests using navGraphViewModels pass without the "does not have a NavController set" exception.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- android, kotlin
- Domain
- mobile, testing
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 35/100