Какие виды тестовых объектов существуют в JUnit и их назначение
Что проверяют
Умеете ли вы строить тесты Android-кода: где они лежат, чем запускаются и чем подменяются зависимости. Следом обычно спрашивают, что вы подставите вместо репозитория в тесте ViewModel: mock или fake.
Как отвечать
Сначала разведите два вида тестов. Локальные лежат в src/test и идут на JVM, быстро. Инструментальные лежат в src/androidTest и запускаются на устройстве или эмуляторе. JUnit 5 в инструментальных тестах работает только через сторонний плагин, поэтому большинство проектов живёт на JUnit 4.
Структура теста в JUnit 4:
- тестовый класс и метод:
@Testна публичном методе, раннер@RunWith(AndroidJUnit4::class); - фикстура:
@Beforeи@Afterвокруг каждого теста, статические@BeforeClassи@AfterClassодин раз на класс; - правила:
@get:Ruleв Kotlin.InstantTaskExecutorRuleделаетLiveDataсинхронной, свойMainDispatcherRuleподменяетDispatchers.MainчерезDispatchers.setMain,createComposeRule()поднимает Compose-экран; - наборы данных и группировка:
@RunWith(Parameterized::class)иSuite.
Тестовые двойники:
- stub: заранее заданный ответ,
every { repo.load() } returns dataв MockK; - mock: проверка взаимодействия,
verify { analytics.track(any()) }; - spy: реальный объект с частичной подменой;
- fake: рабочая упрощённая реализация, например
FakeUserRepositoryнаMutableStateFlow. Руководство Android по тестам называет fake предпочтительным видом двойника.
Корутины проверяются через runTest из kotlinx-coroutines-test: он проматывает delay виртуальным временем.
Где спотыкаются
Пишут инструментальный тест там, где хватило бы локального. Он заметно медленнее и нестабилен в CI, а для кода с классами Android есть Robolectric.
Забывают подменить Dispatchers.Main. Тест ViewModel падает с ошибкой, что Main не инициализирован, и кандидат не может объяснить почему.
Мокают всё подряд, включая data-классы и собственные репозитории. Тесты проверяют порядок вызовов, а не результат, и ломаются при любом рефакторинге.