Android 中的基本测试 NavigationController
Basic testing NavigationController in Android
我目前是测试新手,所以我决定从一些基本的东西开始。
我从连接到 Activity.
的 DrawerLayout 处理所有导航
所以为了我的测试,我启动了一个 ActivityScenarioRule,创建了一个 testNavController 对象,然后我将这个 testNavController 设置为处理导航的当前视图(容器片段)。
所以测试包括打开抽屉,点击菜单项(将导航到片段)因此检查是否导航到片段。
然后我检查是否发生了这种情况,但是 testNavController 停留在同一个目的地 这很奇怪,因为它执行了点击,所以我决定 检查navController (activity 中的真实控制器),并且 它向我展示了导航到正确的片段。
这是所需的代码:
@LargeTest
@RunWith(AndroidJUnit4::class)
class MapsActivityTest {
@get:Rule
var activityScenarioRule = ActivityScenarioRule(MapsActivity::class.java)
@Test
fun clickOnDrawerMaps_NavigateToAboutAppFragment() {
//Create TestNavHostController
val testNavController = TestNavHostController(ApplicationProvider.getApplicationContext())
UiThreadStatement.runOnUiThread { // This needed because it throws a exception that method addObserver must be called in main thread
testNavController.setGraph(R.navigation.nav_graph)
}
val scenario = activityScenarioRule.scenario
var navcontroller : NavController? = null
scenario.onActivity {mapsActivity ->
navcontroller = mapsActivity.navController //Get the real navController just to debug
mapsActivity.navController = testNavController //Set the test navController
Navigation.setViewNavController(mapsActivity.binding.containerFragment, testNavController)
}
onView(withId(R.id.drawerLayout)).perform(DrawerActions.open()).check(matches(isOpen()))
onView(withId(R.id.aboutAppFragment)).perform(click())
assertThat(testNavController.currentDestination?.id).isEqualTo(R.id.aboutAppFragment)
}
}
在示例中,他们使用了片段,他们在片段启动时设置了 fragment.requireView(),但我认为它完全相同。
我做错了什么?
当您使用 ActivityScenario
(或 ActivityScenarioRule
)时,您的 activity 在进行任何 onActivity
调用之前一直处于恢复状态。这意味着当您调用 setupWithNavController
时,您真正的 NavController 已经创建并使用。这就是为什么您对 setViewNavController()
的调用没有效果。
对于这些类型的集成测试(你有一个真正的NavController
),你不应该使用TestNavHostController
。
根据 Test Navigation guide,TestNavHostController
专为根本没有任何真实 NavController
的单元测试而设计,例如单独测试一个片段时。
我目前是测试新手,所以我决定从一些基本的东西开始。
我从连接到 Activity.
的 DrawerLayout 处理所有导航所以为了我的测试,我启动了一个 ActivityScenarioRule,创建了一个 testNavController 对象,然后我将这个 testNavController 设置为处理导航的当前视图(容器片段)。
所以测试包括打开抽屉,点击菜单项(将导航到片段)因此检查是否导航到片段。
然后我检查是否发生了这种情况,但是 testNavController 停留在同一个目的地 这很奇怪,因为它执行了点击,所以我决定 检查navController (activity 中的真实控制器),并且 它向我展示了导航到正确的片段。
这是所需的代码:
@LargeTest
@RunWith(AndroidJUnit4::class)
class MapsActivityTest {
@get:Rule
var activityScenarioRule = ActivityScenarioRule(MapsActivity::class.java)
@Test
fun clickOnDrawerMaps_NavigateToAboutAppFragment() {
//Create TestNavHostController
val testNavController = TestNavHostController(ApplicationProvider.getApplicationContext())
UiThreadStatement.runOnUiThread { // This needed because it throws a exception that method addObserver must be called in main thread
testNavController.setGraph(R.navigation.nav_graph)
}
val scenario = activityScenarioRule.scenario
var navcontroller : NavController? = null
scenario.onActivity {mapsActivity ->
navcontroller = mapsActivity.navController //Get the real navController just to debug
mapsActivity.navController = testNavController //Set the test navController
Navigation.setViewNavController(mapsActivity.binding.containerFragment, testNavController)
}
onView(withId(R.id.drawerLayout)).perform(DrawerActions.open()).check(matches(isOpen()))
onView(withId(R.id.aboutAppFragment)).perform(click())
assertThat(testNavController.currentDestination?.id).isEqualTo(R.id.aboutAppFragment)
}
}
在示例中,他们使用了片段,他们在片段启动时设置了 fragment.requireView(),但我认为它完全相同。
我做错了什么?
当您使用 ActivityScenario
(或 ActivityScenarioRule
)时,您的 activity 在进行任何 onActivity
调用之前一直处于恢复状态。这意味着当您调用 setupWithNavController
时,您真正的 NavController 已经创建并使用。这就是为什么您对 setViewNavController()
的调用没有效果。
对于这些类型的集成测试(你有一个真正的NavController
),你不应该使用TestNavHostController
。
根据 Test Navigation guide,TestNavHostController
专为根本没有任何真实 NavController
的单元测试而设计,例如单独测试一个片段时。