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
}
figured it out. i somehow missed this warning:
all i had to do was change this
bundleOf("listId" to list1.id...)
tobundleOf("listId" to list1.id.toString()...)
(added call totoString()
)not sure why google chose to handle invalid types by turning them into
null
instead of throwing an "InvalidParameter" exception (or similar).