Navigation componentをテストする
Navigation 2.3.0-alpha01からナビゲーションをテストするためのAPIが用意されたので使ってみます。
(2020年2月29日現在、最新バージョンは2.3.0-alpha02です。この記事も2.3.0-alpha02に基づいています。)
従来のNavigationテスト
今までNavigationのテストをする場合、以下のようなテストコードでした。
@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)
}
}
何をテストしているかというと、R.id.play_btn
というViewがクリックされたときに、navigate(R.id.action_title_screen_to_in_game
が呼び出されるかどうか、というのを検証しています。
ただ、呼び出されたからといってActionが望んだ動作をしているのかということまでは保証できません。
例えば、遷移する際にBack stackをpopする場合やargumentを渡す場合などもテストできたら良さそうです。
TestNavHostController
Navigation 2.3.0-alpha01から導入されたのが、TestNavHostController
です。
https://developer.android.com/reference/kotlin/androidx/navigation/testing/TestNavHostController
前まではNavController
をモックしていましたが、TestNavHostController
を使うことでNavController.navigate()
後のCurrent destinationやBack stackにアクセスできるようになります。
@RunWith(AndroidJUnit4::class)
class TitleScreenTest {
@Test
fun testNavigationToInGameScreen() {
// Create a TestNavHostController
val navController = TestNavHostController(
ApplicationProvider.getApplicationContext())
navController.setGraph(R.navigation.trivia)
// 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(), navController)
}
// Verify that performing a click changes the NavController’s state
onView(ViewMatchers.withId(R.id.play_btn)).perform(ViewActions.click())
assertThat(navController.currentDestination?.id).isEqualTo(R.id.in_game)
}
}
注目するところは、assertThat(navController.currentDestination?.id).isEqualTo(R.id.in_game)
という記述。
viewをクリックした後のCurrent destionationのidが、想定しているdestination (Fragment)のidと一致しているか、という検証をしています。
メソッドが呼び出されたかというテストより信頼できます。
Start destinationではないFragmentでのテストを書きたい場合
TestNavHostController.setCurrentDestination()
というメソッドが用意されています。
idをセットすることで指定したdestinationからテストを開始することができます。
val navController = TestNavHostController(
ApplicationProvider.getApplicationContext()
).apply {
setGraph(R.navigation.navigation)
setCurrentDesination(R.id.destination)
}
argumentをテストしたい場合
NavBackStackEntry.arguments
で取得できます。
SafeArgsを利用している場合も同様で、argumentのkeyはnavigation.xmlで指定しているargumentの"name"になります。
val argument = navController.currentBackStackEntry.arguments!!["key"]
assertThat(argument).isEqualTo("hoge")
Back stackをテストしたい場合
TestNavHostController.backStack
ですべてのback stack (List<NavBackStackEntry>
)が取得できます。
もしくは、NavController.previeousBackStackEntry
で現在の一つ前にあるstackを取り出すことができます。
val backStack = navController.backstack
val previous = navController.previousBackStackEntry
assertThat(previous!!.destination.id).isEqualTo(R.id.destination)
参考
https://developer.android.com/guide/navigation/navigation-testing
https://github.com/android/architecture-components-samples/tree/master/NavigationBasicSample
Author And Source
この問題について(Navigation componentをテストする), 我々は、より多くの情報をここで見つけました https://qiita.com/myoshita/items/8aea7ad21cd79a98f573著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .