如何使用导航组件(片段到片段)在Espresso中测试片段导航?

时间:2019-11-17 01:41:29

标签: android android-espresso

当我单击按钮时,我想测试片段导航(从片段到另一个),但是在测试中,它从不导航到目的地。
当我手动测试时,它可以正常工作。
我也在使用导航组件。
我研究并找到了Google的示例代码,但无法运行

我的测试:

@RunWith(AndroidJUnit4::class)
@LargeTest
class OnBoardingFragmentTest{

@Test fun navigationTest(){
    val scenario = launchFragmentInContainer<OnBoardingFragment>()
    onView(withId(R.id.btn_start)).perform(click())
}

按钮的代码单击片段:

btn_start.setOnClickListener { view ->
        Navigation.findNavController(view).navigate(R.id.action_onBoardingFragment_to_loginFragment)
}

来自Google的示例
我尝试使用Google提供的此示例来测试片段导航,但由于无法识别出模仿(无法在kotlin的Mockk库中尝试过),因此无法运行。

@RunWith(AndroidJUnit4::class)
class TitleScreenTest {

@Test
fun testNavigationToInGameScreen() {
    // Create a mock NavController
    val mockNavController = mock(NavController::class.java)

    // Create a graphical FragmentScenario for the TitleScreen
    val titleScenario = launchFragmentInContainer<TitleScreen>()

    // Set the NavController property on the fragment
    titleScenario.onFragment { fragment ->
        Navigation.setViewNavController(fragment.requireView(), mockNavController)
    }

    // Verify that performing a click prompts the correct Navigation action
    onView(ViewMatchers.withId(R.id.play_btn)).perform(ViewActions.click())
    verify(mockNavController).navigate(R.id.action_title_screen_to_in_game)
}

测试时抛出错误:

androidx.test.espresso.PerformException: Error performing 'single click - At Coordinates: 835, 1565 and precision: 16, 16' on view 'with id: tokencash.com.stx.tokencash:id/btn_start'.
at androidx.test.espresso.PerformException$Builder.build(PerformException.java:86)
at androidx.test.espresso.base.DefaultFailureHandler.getUserFriendlyError(DefaultFailureHandler.java:87)
at androidx.test.espresso.base.DefaultFailureHandler.handle(DefaultFailureHandler.java:59)
at androidx.test.espresso.ViewInteraction.waitForAndHandleInteractionResults(ViewInteraction.java:322)
at androidx.test.espresso.ViewInteraction.desugaredPerform(ViewInteraction.java:178)
at androidx.test.espresso.ViewInteraction.perform(ViewInteraction.java:119)
at tokencash.com.stx.OnBoardingFragmentTest.generalTest(OnBoardingFragmentTest.kt:57)
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 org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at androidx.test.internal.runner.junit4.statement.RunBefores.evaluate(RunBefores.java:80)
at androidx.test.rule.ActivityTestRule$ActivityStatement.evaluate(ActivityTestRule.java:531)
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 androidx.test.ext.junit.runners.AndroidJUnit4.run(AndroidJUnit4.java:104)
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:2145)
Caused by: java.lang.IllegalStateException: View androidx.constraintlayout.widget.ConstraintLayout{3c7882 V.E...... ......ID 0,0-1080,1605} does not have a NavController set
at androidx.navigation.Navigation.findNavController(Navigation.java:84)
at tokencash.com.stx.tokencash.fragments.OnBoardingFragment$setListeners$1.onClick(OnBoardingFragment.kt:53)
at android.view.View.performClick(View.java:6597)
at android.view.View.performClickInternal(View.java:6574)
at android.view.View.access$3100(View.java:778)
at android.view.View$PerformClick.run(View.java:25885)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at androidx.test.espresso.base.Interrogator.loopAndInterrogate(Interrogator.java:148)
at androidx.test.espresso.base.UiControllerImpl.loopUntil(UiControllerImpl.java:525)
at androidx.test.espresso.base.UiControllerImpl.loopUntil(UiControllerImpl.java:484)
at androidx.test.espresso.base.UiControllerImpl.injectMotionEvent(UiControllerImpl.java:236)
at androidx.test.espresso.action.MotionEvents.sendUp(MotionEvents.java:162)
at androidx.test.espresso.action.MotionEvents.sendUp(MotionEvents.java:139)
at androidx.test.espresso.action.Tap.sendSingleTap(Tap.java:170)
at androidx.test.espresso.action.Tap.access$100(Tap.java:31)
at androidx.test.espresso.action.Tap$1.sendTap(Tap.java:47)
at androidx.test.espresso.action.GeneralClickAction.perform(GeneralClickAction.java:137)
at androidx.test.espresso.ViewInteraction$SingleExecutionViewAction.perform(ViewInteraction.java:366)
at androidx.test.espresso.ViewInteraction.doPerform(ViewInteraction.java:255)
at androidx.test.espresso.ViewInteraction.access$100(ViewInteraction.java:65)
at androidx.test.espresso.ViewInteraction$1.call(ViewInteraction.java:158)
at androidx.test.espresso.ViewInteraction$1.call(ViewInteraction.java:155)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:193)
at android.app.ActivityThread.main(ActivityThread.java:6669)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)

非常感谢您的帮助:)

1 个答案:

答案 0 :(得分:0)

经过大量测试,我解决了。

要在测试中使用从片段到另一片段的导航,应模拟NavController。
我设置的Mockito错误。

设置Mockito:*

dependencies {
    testImplementation 'org.mockito:mockito-core:2.24.5'
    androidTestImplementation 'org.mockito:mockito-android:2.24.5'
}

在测试中进行静态导入

import org.mockito.Mockito.mock
import org.mockito.Mockito.verify

简单复制并粘贴Google代码

@RunWith(AndroidJUnit4::class)
class TitleScreenTest {

@Test
fun testNavigationToInGameScreen() {
    // Create a mock NavController
    val mockNavController = mock(NavController::class.java)

    // Create a graphical FragmentScenario for the TitleScreen
    val titleScenario = launchFragmentInContainer<TitleScreen>()

    // Set the NavController property on the fragment
    titleScenario.onFragment { fragment ->
        Navigation.setViewNavController(fragment.requireView(), mockNavController)
    }

    // Verify that performing a click prompts the correct Navigation action
    onView(ViewMatchers.withId(R.id.play_btn)).perform(ViewActions.click())
    verify(mockNavController).navigate(R.id.action_title_screen_to_in_game)
}

我希望它可以帮助其他人;)