Robolectric је оквир за јединично тестирање Android апликација који омогућава покретање тестова директно на JVM-у без емулатора или физичког уређаја. Он пресреће позиве Android SDK-а и пружа shadow-објекте који емулирају понашање стварних компоненти. Према Robolectric Documentation, 2025, shadow-објекти замењују око 15 хиљада класа Android API-ја, обезбеђујући изолацију тестова од платформе.
Главно
Robolectric је open-source оквир, креиран 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 компоненте, али ради без нативне платформе.
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 тестови се пишу као обични јединични тестови са @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() и омогућава проверу послатих интената кроз 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, при чему компоненте животног циклуса (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 операције, query са 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 опцијама.
Закључак
Развићемо мобилну апликацију под кључ
IT Sectr креира iOS и Android апликације за стартапе и предузећа од 2017. године. Саветоваћемо вас и предложити најбоље решење.
Прочитајте такође