architecture-samples
architecture-samples copied to clipboard
launchFragmentInHiltContainer doesn't work with navGraphViewModels
Hi,
For test purposes I've modified the code of launchFragmentInHiltContainer
to this:
const val THEME_EXTRAS =
"androidx.fragment.app.testing.FragmentScenario.EmptyFragmentActivity.THEME_EXTRAS_BUNDLE_KEY"
inline fun <reified T : Fragment> 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<HiltTestActivity>(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
:
@Test
fun clickAddTaskButton_navigateToAddEditFragment() {
// GIVEN - On the home screen
val navController = TestNavHostController(ApplicationProvider.getApplicationContext())
navController.setViewModelStore(ViewModelStore())
launchFragmentInHiltContainer<TasksFragment>(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:
private val viewModel
by navGraphViewModels<TasksViewModel>(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?
What if you use this instead?
val navController = TestNavHostController(ApplicationProvider.getApplicationContext())
navController.setGraph(R.navigation.nav_graph)
launchFragmentInHiltContainer<TasksFragment>(navHostController = navController)
I am facing same issue. Any work around?
val mockNavController = mock(NavController::class.java)
launchFragmentInHiltContainer2<SearchListFragment>
{
Navigation.setViewNavController(this.requireView() , mockNavController)
}
in my fragment I am using following. private val navController: NavController by lazy { findNavController() }
Error Fragment SearchListFragment{f12c5e3} (7cd3d967-c7bb-441c-9572-f6acd3c59ae2 id=0x1020002 tag=) does not have a NavController set