我正在为使用safeArgs
和FragmentScenario
的片段编写一个测试,但是当我用fragmentArgs
参数调用launchFragmentInContainer()
时,我得到一个异常,说参数为null。生产代码没有问题。
我的导航图:
<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
的id不为null,因为它是在构造函数中初始化的。
class UserList(
name: String
) : BaseItem(name) {
//class body
}
abstract class BaseItem(
var name: String,
var id: UUID = UUID.randomUUID()
) {
//class body
}
想明白了。不知怎么的,我错过了这个警告:
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()
的调用(
不确定谷歌为什么选择通过将无效类型转换为CCD_ 9来处理它们;InvalidParameter"例外(或类似情况(。
从您的文章中还不清楚UserList
和repoUserLists
类是什么样子的。id
是如何初始化的?您似乎只将name
的一个参数传递给UserList
构造函数。repoUserLists
是否对id
进行初始化?
我的假设是id
实际上是null
,正如异常消息所说的那样。
您是否对仅适用于生产构建而不适用于测试环境的id
进行了一些初始化?
为了验证这一点,您应该在行之后向before
方法添加一行
repoUserLists.addLists(list1)
其验证CCD_ 21实际上不是CCD_。