片段单元测试:launchFragment抛出ClassCastException

问题描述 投票:0回答:1

我试图在单元测试中在我的Fragment类中调用方法,但我不断收到错误java.lang.ClassCastException: androidx.fragment.app.testing.FragmentScenario$EmptyFragmentActivity cannot be cast to com.nu.rms.inspections.ui.activity.InspectionActivity

我正在关注Google的docs。我感到困惑,为什么空的片段活动试图强制转换为我的InspectionActivity(片段所在的父活动),也许这是预期的?

如何减轻CastClassException并在单元测试中使用片段的方法? (related question that doesn't solve my issue

Test

@RunWith(AndroidJUnit4::class)
class ExampleUnitTest {
    @Test
    fun `inspection failure point to location mapping is correct`() {
        val scenario = launchFragment<ContentFragment>()
        scenario.onFragment { fragment ->
            //TODO: test logic
        }
    }
...
}

片段类

import androidx.fragment.app.Fragment
...
class ContentFragment : Fragment() {...}

堆栈跟踪

java.lang.ClassCastException: androidx.fragment.app.testing.FragmentScenario$EmptyFragmentActivity cannot be cast to com.nu.rms.inspections.ui.activity.InspectionActivity
    at com.nu.rms.inspections.ui.fragment.ContentFragment.clearRFIDCache(ContentFragment.kt:565)
    at com.nu.rms.inspections.ui.fragment.ContentFragment.showStep1(ContentFragment.kt:222)
    at com.nu.rms.inspections.ui.fragment.ContentFragment.access$showStep1(ContentFragment.kt:37)
    at com.nu.rms.inspections.ui.fragment.ContentFragment$onViewCreated$1.onChanged(ContentFragment.kt:77)
    at com.nu.rms.inspections.ui.fragment.ContentFragment$onViewCreated$1.onChanged(ContentFragment.kt:37)
    at androidx.lifecycle.LiveData.considerNotify(LiveData.java:113)
    at androidx.lifecycle.LiveData.dispatchingValue(LiveData.java:131)
    at androidx.lifecycle.LiveData.setValue(LiveData.java:289)
    at androidx.lifecycle.MutableLiveData.setValue(MutableLiveData.java:33)
    at androidx.lifecycle.Transformations$2$1.onChanged(Transformations.java:153)
    at androidx.lifecycle.MediatorLiveData$Source.onChanged(MediatorLiveData.java:152)
    at androidx.lifecycle.LiveData.considerNotify(LiveData.java:113)
    at androidx.lifecycle.LiveData.dispatchingValue(LiveData.java:126)
    at androidx.lifecycle.LiveData$ObserverWrapper.activeStateChanged(LiveData.java:424)
    at androidx.lifecycle.LiveData.observeForever(LiveData.java:214)
    at androidx.lifecycle.MediatorLiveData$Source.plug(MediatorLiveData.java:141)
    at androidx.lifecycle.MediatorLiveData.addSource(MediatorLiveData.java:96)
    at androidx.lifecycle.Transformations$2.onChanged(Transformations.java:150)
    at androidx.lifecycle.MediatorLiveData$Source.onChanged(MediatorLiveData.java:152)
    at androidx.lifecycle.LiveData.considerNotify(LiveData.java:113)
    at androidx.lifecycle.LiveData.dispatchingValue(LiveData.java:126)
    at androidx.lifecycle.LiveData$ObserverWrapper.activeStateChanged(LiveData.java:424)
    at androidx.lifecycle.LiveData.observeForever(LiveData.java:214)
    at androidx.lifecycle.MediatorLiveData$Source.plug(MediatorLiveData.java:141)
    at androidx.lifecycle.MediatorLiveData.onActive(MediatorLiveData.java:118)
    at androidx.lifecycle.LiveData$ObserverWrapper.activeStateChanged(LiveData.java:418)
    at androidx.lifecycle.LiveData$LifecycleBoundObserver.onStateChanged(LiveData.java:376)
    at androidx.lifecycle.LifecycleRegistry$ObserverWithState.dispatchEvent(LifecycleRegistry.java:361)
    at androidx.lifecycle.LifecycleRegistry.forwardPass(LifecycleRegistry.java:300)
    at androidx.lifecycle.LifecycleRegistry.sync(LifecycleRegistry.java:339)
    at androidx.lifecycle.LifecycleRegistry.moveToState(LifecycleRegistry.java:145)
    at androidx.lifecycle.LifecycleRegistry.handleLifecycleEvent(LifecycleRegistry.java:131)
    at androidx.fragment.app.FragmentViewLifecycleOwner.handleLifecycleEvent(FragmentViewLifecycleOwner.java:51)
    at androidx.fragment.app.Fragment.performStart(Fragment.java:2639)
    at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManagerImpl.java:915)
    at androidx.fragment.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManagerImpl.java:1238)
    at androidx.fragment.app.FragmentManagerImpl.moveToState(FragmentManagerImpl.java:1303)
    at androidx.fragment.app.BackStackRecord.executeOps(BackStackRecord.java:439)
    at androidx.fragment.app.FragmentManagerImpl.executeOps(FragmentManagerImpl.java:2079)
    at androidx.fragment.app.FragmentManagerImpl.executeOpsTogether(FragmentManagerImpl.java:1869)
    at androidx.fragment.app.FragmentManagerImpl.removeRedundantOperationsAndExecute(FragmentManagerImpl.java:1824)
    at androidx.fragment.app.FragmentManagerImpl.execSingleAction(FragmentManagerImpl.java:1696)
    at androidx.fragment.app.BackStackRecord.commitNow(BackStackRecord.java:293)
    at androidx.fragment.app.testing.FragmentScenario$1.perform(FragmentScenario.java:312)
    at androidx.fragment.app.testing.FragmentScenario$1.perform(FragmentScenario.java:291)
    at androidx.test.core.app.ActivityScenario.lambda$onActivity$1$ActivityScenario(ActivityScenario.java:534)
    at androidx.test.core.app.ActivityScenario$$Lambda$0.run(Unknown Source)
    at org.robolectric.android.fakes.RoboMonitoringInstrumentation.runOnMainSync(RoboMonitoringInstrumentation.java:53)
    at androidx.test.core.app.ActivityScenario.onActivity(ActivityScenario.java:527)
    at androidx.fragment.app.testing.FragmentScenario.internalLaunch(FragmentScenario.java:290)
    at androidx.fragment.app.testing.FragmentScenario.launch(FragmentScenario.java:203)
    at com.nu.rms.inspections.ExampleUnitTest.inspection failure point to location mapping is correct(ExampleUnitTest.kt:56)
    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 org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.robolectric.RobolectricTestRunner$HelperTestRunner$1.evaluate(RobolectricTestRunner.java:600)
    at org.robolectric.internal.SandboxTestRunner$2.evaluate(SandboxTestRunner.java:260)
    at org.robolectric.internal.SandboxTestRunner.runChild(SandboxTestRunner.java:130)
    at org.robolectric.internal.SandboxTestRunner.runChild(SandboxTestRunner.java:42)
    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.robolectric.internal.SandboxTestRunner$1.evaluate(SandboxTestRunner.java:84)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at androidx.test.runner.AndroidJUnit4.run(AndroidJUnit4.java:104)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
    at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
android unit-testing android-fragments testing android-fragmentactivity
1个回答
0
投票
这意味着您的片段在您的InspectionActivity类的实例中为

not。您正在崩溃,因为您的clearRFIDCache()方法将活动投射到InspectionActivity

如果您需要在Activity的特定实例中测试您的Fragment并在两者之间建立牢固的耦合,则需要使用ActivityScenario并将Fragment手动添加到该Activity中,而不是使用FragmentScenario您无法控制您正在使用的活动类。

理想情况下,您

不应

将片段与活动紧密结合在一起。例如,您可以提供一个FragmentFactory,它使用构造函数注入来添加Fragment所需的接口,而不是您的Fragment到达Activity来直接调用Fragments: Past, Present, and Future talk中讨论的方法。

[launchFragment带有factory参数,该参数允许您注入测试接口,确保您可以在不依赖于活动的特定子类的情况下检查是否获得了期望的回调。

© www.soinside.com 2019 - 2024. All rights reserved.