аргументы фрагмента равны нулю при использовании launchFragmentInContainer

Я пишу тест для фрагмента, который использует safeArgs а также FragmentScenarioно когда я звоню launchFragmentInContainer() с fragmentArgsпараметр, я получаю исключение, сообщающее, что аргументы равны нулю. В производственном коде проблем нет.

Мой график навигации:

<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>

Мой тест:

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
        )
    }

когда я пытаюсь запустить тест, я получаю

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

полная трассировка стека:

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

Редактировать:

Идентификатор List1 не равно нулю, так как он инициализируется в конструкторе.

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

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

    //class body
}

2 ответа

Решение

Догадаться . я как-то пропустил это предупреждение:

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

все, что мне нужно было сделать, это изменить это bundleOf("listId" to list1.id...) к bundleOf("listId" to list1.id.toString()...) (добавлен звонок в toString())

не уверен, почему Google решил обрабатывать недопустимые типы, превращая их в null вместо того, чтобы генерировать исключение InvalidParameter (или подобное).

Из вашего поста непонятно, что за UserList а также repoUserListsклассы похожи. Какidинициализирован? Кажется, вы передаете параметр только дляname к UserListконструктор. ДелаетrepoUserLists выполнить инициализацию id?

Я предполагаю, что id на самом деле null, как указано в сообщении об исключении.

У вас есть инициализация id что работает только для производственных сборок, а не в тестовой среде?

Чтобы проверить это, вы должны добавить строку в свой before метод после строки

repoUserLists.addLists(list1)

это подтверждает list1.id на самом деле не null.

Другие вопросы по тегам