#android #testing #android-espresso #instrumented-test
#Android #тестирование #android-espresso #инструментальный-тест
Вопрос:
В настоящее время я новичок в тестировании, поэтому решил начать с некоторых базовых вещей.
Я обрабатываю все свои навигации из 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() при запуске фрагмента, но я думаю, что это точно то же самое.
Что я здесь делаю не так?
Комментарии:
1. Есть ли причина
TestNavHostController
, по которой вы вообще используете a, если ваша активность уже имеет realNavController
?2. Мое предположение, когда я начал тестирование, состояло в том, чтобы использовать что-то «поддельное» при тестировании вместо «реального» только для улучшения практики, но я снова только начал с тестирования, и я супер невежественен! Итак, я предполагаю, что мы устанавливаем TestNavController только при использовании фрагментов, потому что activity пуста, верно? @ianhanniballake
Ответ №1:
Когда вы используете ActivityScenario
(или ActivityScenarioRule
), ваша активность полностью переводится в возобновленное состояние, прежде onActivity
чем будут сделаны какие-либо вызовы. Это означает , что ваш реальный NavController уже создан и используется при вызове setupWithNavController
. Вот почему ваш призыв к setViewNavController()
не имеет никакого эффекта.
Для этих типов интеграционных тестов (где у вас есть real NavController
) вы не должны использовать TestNavHostController
.
Согласно руководству по навигации по тестированию, TestNavHostController
предназначен для модульных тестов, в которых у вас вообще нет реального NavController
, например, при изолированном тестировании одного фрагмента.
Комментарии:
1. Теперь это имеет большой смысл! Большое вам спасибо за ваше объяснение 🙂