Robolectric е рамка за unit тестване на Android приложения, която позволява стартиране на тестове директно на JVM без емулатор или физическо устройство. Тя прихваща извикванията на Android SDK и предоставя shadow-обекти, емулиращи поведението на реални компоненти. Според Robolectric Documentation, 2025, shadow-обектите заместват около 15 хиляди класа на Android API, осигурявайки изолация на тестовете от платформата.
Основни точки
Robolectric е рамка с отворен код, създадена през 2010 г. за ускоряване на тестването на Android приложения. Вместо да работи на емулатор или устройство, Robolectric предоставя shadow-имплементации на класове от Android SDK, които работят директно на Java Virtual Machine (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 компонент, но работи без native платформа.
Shadow-обектите имплементират ключовите методи на оригиналните Android класове. Например ShadowTextView имитира методите getText(), setText(), getCurrentTextColor() и други. При извикване на textView.setText(„Hello“) 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“. Също така трябва да се посочи конфигурацията android:sdk във файла build.gradle и да се добави android:testInstrumentationRunner. За работа с Robolectric не е необходим плъгин android-test.
След добавяне на зависимостта трябва да се конфигурира директорията за манифест, ресурси и активи. 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 тестовете се пишат като обикновени unit тестове с @RunWith(RobolectricTestRunner.class) за JUnit 4 или чрез RobolectricExtension за JUnit 5. ActivityController управлява жизнения цикъл на Activity: create(), start(), resume(), pause(), stop(), destroy(). Това позволява детайлно тестване на всяко преминаване на състояние.
За тестване на Activity се използва ActivityController, който последователно преминава през фазите на жизнения цикъл. Достъпът до Activity е чрез controller.get(). Всички компоненти на изгледа са достъпни чрез 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() и позволява проверка на изпратените intent-ове чрез 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 е идеален за бързи unit тестове, проверка на UI логика, бизнес компоненти и хранилища. Емулаторът е необходим за инструментационни тестове, проверка на интеграция с API, тестване на камера, сензори и производителност.
| Характеристика | Robolectric | Емулатор |
|---|---|---|
| Скорост | ~5 сек на 100 теста | ~5 мин на 100 теста |
| Стартиране | Без изграждане на APK | Изисква изграждане на APK |
| Реално API | Shadow-емулация | Native Android SDK |
| Out-of-the-box | Само JUnit | Всякакви рамки |
Robolectric е отличен за тестване на ViewModel, Repository и UseCase — компоненти, които използват Android SDK, но не изискват реален UI. ViewModel се тества чрез обикновен JUnit тест с RobolectricExtension, като компонентите на жизнения цикъл (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. Персонализираните shadow-ове се регистрират чрез @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, биометрия, работа с реални файлове и native библиотеки. За тези сценарии са необходими инструментационни тестове на емулатора. 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 е unit рамка, работеща на 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.
Обобщение
Ще разработим мобилно приложение под ключ
IT Sectr създава iOS и Android приложения за стартъпи и бизнеси от 2017 г. Ще ви консултираме и ще предложим най-доброто решение.
Прочетете също