0

I have a fragment which waits for an integer from args. The code itself works fine, but when I want to write a UI test for this fragment it gives me a

java.lang.NullPointerException: null cannot be cast to non-null type kotlin.Int at androidx.navigation.NavType$Companion$IntType$1.get(NavType.kt:320) at androidx.navigation.NavType$Companion$IntType$1.get(NavType.kt:310) at androidx.navigation.NavArgument.verify(NavArgument.kt:76) at androidx.navigation.NavDestination.addInDefaultArgs(NavDestination.kt:603) at androidx.navigation.NavController.navigate(NavController.kt:1855) at androidx.navigation.NavController.handleDeepLink(NavController.kt:1414) at androidx.navigation.testing.TestNavHostController.setCurrentDestination(TestNavHostController.kt:51) at androidx.navigation.testing.TestNavHostController.setCurrentDestination$default(TestNavHostController.kt:47) at com.wolfpackdigital.extrakarte.base.BaseUITest.setupNavigation(BaseUITest.kt:130)`
The line which this refers to is
`navController.setCurrentDestination(R.id.MyFragment)

I initialize my scenario like this:

val bundle = bundleOf(
   "myParam" to 3
)
scenario = launchFragmentInContainer(themeResId = R.style.AppTheme, fragmentArgs = bundle)

With every other type of parameter it works (String, custom data model), but with integer it just doesn't cooperate with me.

Any ideas?

1 Answer 1

0

You have not provided your launchFragmentInContainer implementation but I will answer based on my current setup and experience with fragments. This is the implementation I have (note we are using Hilt but it should be similar).

inline fun <reified T : Fragment> launchFragmentInHiltContainer(
        fragmentArgs: Bundle? = null,
        themeResId: Int = R.style.AppTheme,
        fragmentFactory: FragmentFactory? = null,
        crossinline action: T.() -> Unit = {}
    ) {
        val mainActivityIntent = Intent.makeMainActivity(
            ComponentName(
                ApplicationProvider.getApplicationContext(),
                HiltTestActivity::class.java
            )
        ).putExtra(
            "androidx.fragment.app.testing.FragmentScenario.EmptyFragmentActivity.THEME_EXTRAS_BUNDLE_KEY",
            themeResId
        )

        ActivityScenario.launch<HiltTestActivity>(mainActivityIntent).onActivity { activity ->
            fragmentFactory?.let {
                activity.supportFragmentManager.fragmentFactory = it
            }
            val fragment = activity.supportFragmentManager.fragmentFactory.instantiate(
                Preconditions.checkNotNull(T::class.java.classLoader),
                T::class.java.name
            )
            fragment.arguments = fragmentArgs

            activity.supportFragmentManager.beginTransaction()
                .add(android.R.id.content, fragment, "")
                .commitNow()

            (fragment as T).action()
        }

    }

Let's say you want to start a specific fragment named MyView, for this(and each fragment) you should have MyViewArgs(or similar) object. Then you can start it in this way:

val args = MyViewArgs(11111).toBundle()     
HiltFragmentUtil.launchFragmentInHiltContainer<MyView>(args)

This way you are providing the args the exact way the fragment expects them so if the arg is an int, then MyViewArgs will require it as int

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.