Robolectric — це фреймворк для юніт-тестування Android-застосунків, який дозволяє запускати тести безпосередньо на JVM без емулятора або фізичного пристрою. Він перехоплює виклики Android SDK і надає shadow-об'єкти, що емулюють поведінку реальних компонентів. За даними Robolectric Documentation, 2025, shadow-об'єкти замінюють близько 15 тисяч класів Android API, забезпечуючи ізоляцію тестів від платформи.
Головне
Robolectric — це open-source фреймворк, створений у 2010 році для прискорення тестування Android-застосунків. Замість запуску на емуляторі або пристрої, Robolectric надає shadow-реалізації класів Android SDK, які працюють безпосередньо на віртуальній машині Java (JVM). Це дозволяє виконувати тисячі тестів за секунди.
Традиційне Android-тестування вимагає запуску застосунку на емуляторі, що займає 3–10 хвилин на збірку APK, встановлення та запуск. Robolectric усуває цей крок: тести компілюються як звичайні Java/Kotlin-тести та запускаються через JUnit. Це дає цикл зворотного зв'язку в кілька секунд замість хвилин.
Robolectric підтримує всі версії Android починаючи з API 16 (Android 4.1) і до останньої стабільної. Для кожної версії надається відповідний набір shadow-об'єктів, які емулюють поведінку саме тієї версії платформи, на якій тестується застосунок.
Архітектура Robolectric заснована на механізмі перехоплення викликів через підміну classloader'а. Коли тест викликає метод Android SDK, Robolectric перехоплює виклик і направляє його в shadow-об'єкт. Shadow-об'єкт — це Java-клас, який імітує реальну поведінку Android-компонента, але працює без нативної платформи.
Shadow-об'єкти реалізують ключові методи оригінальних Android-класів. Наприклад, ShadowTextView імітує методи getText(), setText(), getCurrentTextColor() та інші. При виклику textView.setText("Привіт") shadow зберігає рядок і повертає його при виклику getText(). Це ізолює тести від реального рендерингу та системних сервісів.
Robolectric підтримує більше 200 shadow-класів, що покривають основні компоненти Android SDK: Activity, Fragment, TextView, Button, RecyclerView, WebView, LocationManager, ConnectivityManager та багато інших. Shadow-об'єкти слідують тій самій ієрархії успадкування, що й оригінальні класи Android.
Встановлення Robolectric в проект Gradle вимагає додавання залежності testImplementation "org.robolectric:robolectric:4.x". Також необхідно вказати androidsdk-конфігурацію у файлі build.gradle та додати роздільну здатність android:testInstrumentationRunner. Для роботи з Robolectric не потрібен плагін android-тестів.
Після додавання залежності потрібно сконфігурувати директорію для маніфесту, ресурсів та асетів. Robolectric автоматично знаходить AndroidManifest.xml, але може знадобитися вказати шлях вручну через @Config-анотацію або системні властивості. Для мультимодульних проєктів конфігурація задається окремо для кожного модуля.
// build.gradle — налаштування Robolectric
android {
testOptions {
unitTests.includeAndroidResources = true
unitTests.all {
systemProperty 'robolectric.dependency.dir',
project.rootDir.absolutePath + '/build/intermediates'
}
}
}
dependencies {
testImplementation 'org.robolectric:robolectric:4.13'
testImplementation 'org.junit.jupiter:junit-jupiter:5.10.0'
}
Анотація @Config дозволяє перевизначити параметри тесту: sdk (версія API), manifest (шлях до маніфесту), qualifiers (конфігурація екрану, мова). Це корисно для тестування поведінки застосунку на різних версіях Android, орієнтаціях екрану та локалізаціях.
Тести Robolectric пишуться як звичайні юніт-тести з @RunWith(RobolectricTestRunner.class) для JUnit 4 або через RobolectricExtension для JUnit 5. ActivityController керує життєвим циклом Activity: create(), start(), resume(), pause(), stop(), destroy(). Це дозволяє детально тестувати кожен перехід стану.
Для тестування Activity використовується ActivityController, який послідовно проходить через стадії життєвого циклу. Доступ до Activity здійснюється через controller.get(). Всі view-компоненти доступні через findViewById, як у реальному застосунку. Shadow-об'єкти дозволяють перевірити тексти, видимість, кольори та інші атрибути в'ю.
@RunWith(RobolectricTestRunner.class)
@Config(sdk = BuildConfig.SDK_INT)
public class MainActivityTest {
@Test
public void testActivityDisplaysGreeting() {
ActivityController<MainActivity> controller =
Robolectric.buildActivity(MainActivity.class);
controller.create().start().resume();
MainActivity activity = controller.get();
TextView greeting = activity.findViewById(R.id.greeting);
ShadowTextView shadow = Shadows.shadowOf(greeting);
assertEquals("Welcome!", shadow.getText());
}
}
Robolectric перехоплює виклики startActivity() і дозволяє перевірити відправлені інтенти через ShadowActivity. Це дає можливість тестувати навігацію: перевірити, що при натисканні на кнопку відправляється Intent з правильним Action, Data та Extra-параметрами.
@Test
public void testNavigationToDetails() {
controller.create().start().resume();
MainActivity activity = controller.get();
activity.findViewById(R.id.detailsButton).performClick();
ShadowActivity shadowActivity = Shadows.shadowOf(activity);
Intent intent = shadowActivity.getNextStartedActivity();
assertEquals(
DetailsActivity.class.getName(),
intent.getComponent().getClassName()
);
}
Robolectric і емулятор вирішують різні завдання. Robolectric ідеальний для швидких юніт-тестів, перевірки логіки UI, бізнес-компонентів та репозиторіїв. Емулятор необхідний для інструментаційних тестів, перевірки інтеграції з API, тестування камери, датчиків та продуктивності.
| Характеристика | Robolectric | Емулятор |
|---|---|---|
| Швидкість | ~5 сек на 100 тестів | ~5 хв на 100 тестів |
| Запуск | Без збірки APK | Потрібна збірка APK |
| Реальне API | Shadow-емуляція | Нативний Android SDK |
| Out-of-the-box | Тільки JUnit | Будь-які фреймворки |
Robolectric чудово підходить для тестування ViewModel, Repository та UseCase — компонентів, які використовують Android SDK, але не потребують реального UI. ViewModel тестується через звичайний JUnit-тест з RobolectricExtension, при цьому lifecycle-компоненти (LiveData, StateFlow) працюють у shadow-середовищі без моків.
Robolectric підтримує LiveData з коробки: можна підписатися на LiveData в тесті, змінити стан через ViewModel та перевірити емітоване значення. Для асинхронних операцій використовується InstantTaskExecutorRule або runBlocking для корутин. Це позбавляє від необхідності мокати архітектурні компоненти.
@RunWith(RobolectricTestRunner::class)
@Config(sdk = [BuildConfig.SDK_INT])
class ProfileViewModelTest {
private val repository = FakeUserRepository()
private val viewModel = ProfileViewModel(repository)
@Test
fun `loading profile sets state to success`() = runBlocking {
viewModel.loadProfile("user123")
val state = viewModel.profileState.getOrAwaitValue()
Assertions.assertTrue(state is UiState.Success)
}
}
Якщо стандартні shadow-об'єкти Robolectric не покривають потрібний клас Android SDK, можна створити кастомний Shadow. Для цього створюється клас з анотацією @Implements(ClassName.class) та реалізуються потрібні методи з @Implementation. Кастомні shadows реєструються через @Config(shadows = [CustomShadow::class]).
Robolectric підтримує тестування ContentProvider через Robolectric.buildContentProvider(). Можна перевірити CRUD-операції, запити з URI-матчингом та обробку прав доступу. Ресурси (рядки, кольори, розміри) також доступні через RuntimeEnvironment.application.resources, що дозволяє тестувати код, залежний від ресурсів.
Перехід з інструментаційних тестів на Robolectric вимагає зміни підходу. Інструментаційні тести (AndroidJUnit4) перевіряють реальну поведінку на емуляторі, Robolectric — ізольовану логіку в shadow-середовищі. Рекомендується покривати Robolectric-тестами бізнес-логіку, а інструментаційні тести залишити для інтеграційних сценаріїв.
При міграції потрібно: замінити AndroidJUnit4 на RobolectricTestRunner, додати @Config з цільовою версією SDK, замінити ActivityTestRule на ActivityController та перенести залежності з androidTestImplementation в testImplementation. Моки (MockK, Mockito) працюють з Robolectric без змін — вони не залежать від платформи.
Robolectric не підтримує: тестування камери (CameraX), NFC, Bluetooth, біометрію, роботу з реальними файлами та нативними бібліотеками. Для цих сценаріїв необхідні інструментаційні тести на емуляторі. Robolectric також не відтворює реальний рендеринг — тести верстки краще виконувати через Compose Test Rule або Espresso. Однак для перевірки бізнес-логіки, навігації та станів ViewModel Robolectric повністю замінює емулятор з 10-кратним прискоренням прогону.
Robolectric вимагає JDK 11 або вище і сумісний з AGP (Android Gradle Plugin) від 7.0 до останньої стабільної версії. SDK-менеджер Robolectric автоматично завантажує необхідні версії Android API при першому запуску — це одноразова операція. Для CI-серверів рекомендується попередньо завантажити SDK через sdkmanager, щоб уникнути затримок при першому прогоні тестів. Оновлення Robolectric до нової версії зазвичай не вимагає змін у коді тестів, тільки оновлення номера залежності в build.gradle.
Robolectric сумісний з популярними mocking-фреймворками: MockK для Kotlin та Mockito для Java. Моки використовуються для ізоляції залежностей: репозиторіїв, API-клієнтів, SharedPreferences. Головне правило — не мокати класи Android SDK, для цього є shadow-об'єкти. Мокайте тільки шари застосунку: UseCase, Repository, DataSource та інші компоненти бізнес-логіки. Така комбінація shadow-об'єктів та моків дає максимальну гнучкість при мінімальних витратах на написання тестів.
Часто задавані питання
Espresso — це інструментаційний фреймворк, що запускається на емуляторі або пристрої. Robolectric — це юніт-фреймворк, що працює на JVM. Espresso тестує реальну поведінку, Robolectric — ізольовану логіку в shadow-середовищі. Вони доповнюють один одного.
Так, Robolectric підтримує Jetpack Compose починаючи з версії 4.8. Тести Compose-компонентів виконуються за допомогою ComposeTestRule, аналогічно емулятору. Однак Compose-тести на Robolectric не перевіряють реальний рендеринг — тільки логіку композиції.
Robolectric підтримує мультимодульні проєкти. Кожен модуль налаштовується окремо із зазначенням свого маніфесту та ресурсів. Для модулів без UI-компонентів достатньо бібліотечного модуля без android-плагіна. У великих проєктах з десятками модулів Robolectric тести кожного модуля запускаються паралельно, що дає додатковий виграш у швидкості порівняно з послідовним прогоном на емуляторі.
Проблема з ресурсами виникає, якщо в build.gradle не вказано unitTests.includeAndroidResources = true або відсутня @Config-анотація з правильним шляхом до маніфесту. Robolectric використовує скомпільовані ресурси з build/intermediates.
Robolectric-тести налагоджуються як звичайні Java/Kotlin-тести в Android Studio. Доступний breakpoint, step-through debug, інспекція shadow-об'єктів та їх стану. Логування вмикається через -Drobolectric.logging=debug в VM options.
Підсумки
Ми розробимо мобільний застосунок під ключ
IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.
Читайте також