or_dvir
or_dvir

Reputation: 619

fragment arguments are null using launchFragmentInContainer

I am writing a test for a fragment that uses safeArgs and FragmentScenario, however when I call launchFragmentInContainer() with the fragmentArgs parameter, I get an exception saying the arguments are null. There is no problem in production code.

My navigation graph:

<fragment
        android:id="@+id/fragmentNewListItems"
        android:name="com.hotmail.or_dvir.arislistkt2.vvm.FragmentNewListItems"
        android:label="@string/title_newItems"
        tools:layout="@layout/fragment_new_list_items">

        <argument
            android:name="listId"
            app:argType="string" />
        <argument
            android:name="listName"
            app:argType="string" />
    </fragment>

My test:

class TesFragmentNewListItems : BaseAndroidTest() {
    private lateinit var fragScenario: FragmentScenario<FragmentNewListItems>

    private val list1 = UserList("list 1")

    @Before
    fun before() {
        //adding a user list to add items to
        repoUserLists.addLists(list1)
        fragScenario = this.launchFragment(
            //setting arguments here
            bundleOf("listId" to list1.id, "listName" to list1.name)
        )
    }


    inline fun <reified T : Fragment> launchFragment(args: Bundle): FragmentScenario<T> {
        return launchFragmentInContainer<T>(
            themeResId = R.style.AppTheme,
            fragmentArgs = args
        )
    }

when i try to run the test i get

Caused by: java.lang.IllegalArgumentException: Argument "listId" is marked as non-null but was passed a null value.

full stack trace:

java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
at androidx.test.runner.MonitoringInstrumentation.runOnMainSync(MonitoringInstrumentation.java:441)
at androidx.test.core.app.ActivityScenario.onActivity(ActivityScenario.java:564)
at androidx.fragment.app.testing.FragmentScenario.internalLaunch(FragmentScenario.java:300)
at androidx.fragment.app.testing.FragmentScenario.launchInContainer(FragmentScenario.java:282)
at com.hotmail.or_dvir.arislistkt2.TesFragmentNewListItems.before(TesFragmentNewListItems.kt:79)
at java.lang.reflect.Method.invoke(Native Method)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at androidx.test.internal.runner.junit4.statement.RunBefores.evaluate(RunBefores.java:76)
at androidx.test.internal.runner.junit4.statement.RunAfters.evaluate(RunAfters.java:61)
at org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:55)
at org.koin.test.mock.MockProviderRule$apply$1.evaluate(MockProviderRule.kt:13)
at org.junit.rules.TestWatcher$1.evaluate(TestWatcher.java:55)
at org.junit.rules.RunRules.evaluate(RunRules.java:20)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runners.Suite.runChild(Suite.java:128)
at org.junit.runners.Suite.runChild(Suite.java:27)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
at androidx.test.internal.runner.TestExecutor.execute(TestExecutor.java:56)
at androidx.test.runner.AndroidJUnitRunner.onStart(AndroidJUnitRunner.java:392)
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:2189)
Caused by: java.lang.reflect.InvocationTargetException
at java.lang.reflect.Method.invoke(Native Method)
at androidx.navigation.NavArgsLazy.getValue(NavArgsLazy.kt:52)
at androidx.navigation.NavArgsLazy.getValue(NavArgsLazy.kt:34)
at com.hotmail.or_dvir.arislistkt2.vvm.FragmentNewListItems.getFragArgs(Unknown Source:4)
at com.hotmail.or_dvir.arislistkt2.vvm.FragmentNewListItems.onViewCreated(FragmentNewListItems.kt:31)
at androidx.fragment.app.FragmentStateManager.createView(FragmentStateManager.java:332)
at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1199)
at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1368)
at androidx.fragment.app.FragmentManager.moveFragmentToExpectedState(FragmentManager.java:1446)
at androidx.fragment.app.FragmentManager.moveToState(FragmentManager.java:1509)
at androidx.fragment.app.BackStackRecord.executeOps(BackStackRecord.java:447)
at androidx.fragment.app.FragmentManager.executeOps(FragmentManager.java:2181)
at androidx.fragment.app.FragmentManager.executeOpsTogether(FragmentManager.java:2004)
at androidx.fragment.app.FragmentManager.removeRedundantOperationsAndExecute(FragmentManager.java:1959)
at androidx.fragment.app.FragmentManager.execSingleAction(FragmentManager.java:1830)
at androidx.fragment.app.BackStackRecord.commitNow(BackStackRecord.java:297)
at androidx.fragment.app.testing.FragmentScenario$1.perform(FragmentScenario.java:317)
at androidx.fragment.app.testing.FragmentScenario$1.perform(FragmentScenario.java:301)
at androidx.test.core.app.ActivityScenario.lambda$onActivity$2$ActivityScenario(ActivityScenario.java:551)
at androidx.test.core.app.ActivityScenario$$Lambda$4.run(Unknown Source:4)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:462)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at android.app.Instrumentation$SyncRunnable.run(Instrumentation.java:2207)
at android.os.Handler.handleCallback(Handler.java:883)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:7356)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
Caused by: java.lang.IllegalArgumentException: Argument "listId" is marked as non-null but was passed a null value.
at com.hotmail.or_dvir.arislistkt2.vvm.FragmentNewListItemsArgs$Companion.fromBundle(FragmentNewListItemsArgs.kt:28)
at com.hotmail.or_dvir.arislistkt2.vvm.FragmentNewListItemsArgs.fromBundle(Unknown Source:2)
... 30 more

Edit:

The id of List1 is not null as it is initialized in the constructor.

class UserList(
    name: String
) : BaseItem(name) {

    //class body
}
abstract class BaseItem(
    var name: String,
    var id: UUID = UUID.randomUUID()
) {

    //class body
}

Upvotes: 1

Views: 2748

Answers (2)

or_dvir
or_dvir

Reputation: 619

figured it out. i somehow missed this warning:

W/Bundle: Key listId expected String but value was a java.util.UUID.  The default value <null> was returned.

all i had to do was change this bundleOf("listId" to list1.id...) to bundleOf("listId" to list1.id.toString()...) (added call to toString())

not sure why google chose to handle invalid types by turning them into null instead of throwing an "InvalidParameter" exception (or similar).

Upvotes: 2

Marco Lierfeld
Marco Lierfeld

Reputation: 21

From your post it is not clear, what the UserList and repoUserLists classes looks like. How is id initialized? You only seem to pass a parameter for the name to the UserList constructor. Does repoUserLists do the initialization of the id?

My assumption would be that id is in fact null, as the exception message states.

Do you have some initialization of the id that only works for production builds, not in the test environment?

To verify this you should add a line to your before method after line

repoUserLists.addLists(list1)

that verifies list1.id is actually not null.

Upvotes: 0

Related Questions