A Robolectric egy keretrendszer Android alkalmazások egységteszteléséhez, amely lehetővé teszi tesztek közvetlen JVM-en történő futtatását emulátor vagy fizikai eszköz nélkül. Elfogja az Android SDK hívásait, és shadow-objektumokat biztosít, amelyek a valós komponensek viselkedését emulálják. A Robolectric Documentation, 2025 szerint a shadow-objektumok körülbelül 15 ezer Android API osztályt helyettesítenek, biztosítva a tesztek platformtól való elkülönítését.
Főbb pontok
Robolectric egy nyílt forráskódú keretrendszer, amelyet 2010-ben hoztak létre az Android alkalmazások tesztelésének felgyorsítására. Ahelyett, hogy emulátoron vagy eszközön futna, a Robolectric az Android SDK osztályainak shadow-megvalósításait biztosítja, amelyek közvetlenül a Java Virtual Machine-en (JVM) működnek. Ez lehetővé teszi több ezer teszt másodpercek alatti végrehajtását.
A hagyományos Android tesztelés megköveteli az alkalmazás emulátoron történő futtatását, ami 3–10 percet vesz igénybe az APK felépítéséhez, telepítéséhez és indításához. A Robolectric kiküszöböli ezt a lépést: a tesztek hétköznapi Java/Kotlin tesztekként fordulnak és JUnit-on keresztül futnak. Ez néhány másodperces visszacsatolási ciklust biztosít percek helyett.
A Robolectric támogatja az összes Android verziót API 16-tól (Android 4.1) a legutolsó stabil verzióig. Minden verzióhoz biztosítja a megfelelő shadow-objektumok készletét, amelyek pontosan annak a platformverziónak a viselkedését emulálják, amelyen az alkalmazást tesztelik.
A Robolectric architektúrája a hívások elfogásának mechanizmusán alapul a classloader helyettesítésén keresztül. Amikor egy teszt meghív egy Android SDK metódust, a Robolectric elfogja a hívást és a shadow-objektumhoz irányítja. Shadow-objektum egy Java osztály, amely utánozza az Android komponens valós viselkedését, de natív platform nélkül működik.
A shadow-objektumok megvalósítják az eredeti Android osztályok kulcsmetódusait. Például a ShadowTextView imitálja a getText(), setText(), getCurrentTextColor() és más metódusokat. A textView.setText(„Hello“) hívásakor a shadow eltárolja a sztringet, és visszaadja a getText() hívásakor. Ez elkülöníti a teszteket a valós megjelenítéstől és rendszerszolgáltatásoktól.
A Robolectric több mint 200 shadow-osztályt támogat, amelyek lefedik az Android SDK fő komponenseit: Activity, Fragment, TextView, Button, RecyclerView, WebView, LocationManager, ConnectivityManager és még sok más. A shadow-objektumok ugyanazt az öröklődési hierarchiát követik, mint az eredeti Android osztályok.
A Robolectric telepítése Gradle projektben a testImplementation „org.robolectric:robolectric:4.x“ függőség hozzáadását igényli. Szintén meg kell adni az android:sdk konfigurációt a build.gradle fájlban, és hozzáadni az android:testInstrumentationRunnert. A Robolectric-hez nem szükséges az android-test plugin.
A függőség hozzáadása után konfigurálni kell a könyvtárat a manifest, erőforrások és assetek számára. A Robolectric automatikusan megtalálja az AndroidManifest.xml-t, de szükség lehet az útvonal kézi megadására a @Config annotáción vagy rendszerparamétereken keresztül. Többmodulos projekteknél a konfigurációt modulonként külön kell beállítani.
// build.gradle — Robolectric konfigurációja
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'
}
A @Config annotáció lehetővé teszi a teszt paramétereinek felülírását: sdk (API verzió), manifest (útvonal a manifesthez), qualifiers (képernyő konfiguráció, nyelv). Ez hasznos az alkalmazás viselkedésének teszteléséhez különböző Android verziókon, képernyő tájolásokon és lokalizációkon.
A Robolectric teszteket hétköznapi egységtesztként írják a @RunWith(RobolectricTestRunner.class) segítségével JUnit 4-hez vagy RobolectricExtension-en keresztül JUnit 5-höz. ActivityController kezeli az Activity életciklusát: create(), start(), resume(), pause(), stop(), destroy(). Ez lehetővé teszi minden állapotátmenet részletes tesztelését.
Az Activity teszteléséhez ActivityController-t használunk, amely szekvenciálisan halad át az életciklus fázisain. Az Activity-hez a controller.get()-en keresztül férünk hozzá. Az összes nézetkomponens elérhető a findViewById-n keresztül, mint egy valós alkalmazásban. A shadow-objektumok lehetővé teszik a szövegek, láthatóság, színek és egyéb nézetattribútumok ellenőrzését.
@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());
}
}
A Robolectric elfogja a startActivity() hívásokat, és lehetővé teszi az elküldött intentek ellenőrzését a ShadowActivity-n keresztül. Ez lehetőséget ad a navigáció tesztelésére: annak ellenőrzésére, hogy egy gomb megnyomásakor a megfelelő Action, Data és Extra paraméterekkel rendelkező Intent kerül elküldésre.
@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()
);
}
A Robolectric és az emulátor különböző feladatokat old meg. A Robolectric ideális gyors egységtesztekhez, UI logika, üzleti komponensek és adattárak ellenőrzéséhez. Az emulátor az instrumentációs tesztekhez, API integráció ellenőrzéséhez, kamera, érzékelők és teljesítmény teszteléséhez szükséges.
| Jellemző | Robolectric | Emulátor |
|---|---|---|
| Sebesség | ~5 mp 100 tesztre | ~5 perc 100 tesztre |
| Indítás | APK építés nélkül | APK építés szükséges |
| Valós API | Shadow-emuláció | Natív Android SDK |
| Out-of-the-box | Csak JUnit | Bármely keretrendszer |
A Robolectric kiválóan alkalmas ViewModel, Repository és UseCase tesztelésére — olyan komponenseké, amelyek használják az Android SDK-t, de nem igényelnek valós UI-t. ViewModel egy szokásos JUnit teszttel tesztelhető RobolectricExtension segítségével, ahol az életciklus komponensek (LiveData, StateFlow) shadow-környezetben működnek mock-ok nélkül.
A Robolectric támogatja a LiveData-t dobozból: fel lehet iratkozni a LiveData-ra a tesztben, megváltoztatni az állapotot ViewModel-en keresztül, és ellenőrizni a kibocsátott értéket. Aszinkron műveletekhez InstantTaskExecutorRule vagy runBlocking használható a coroutine-okhoz. Ez kiküszöböli az architekturális komponensek mockolásának szükségességét.
@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)
}
}
Ha a Robolectric szabványos shadow-objektumai nem fedik le a szükséges Android SDK osztályt, létrehozható egyedi Shadow. Ehhez létre kell hozni egy osztályt @Implements(ClassName.class) annotációval, és meg kell valósítani a szükséges metódusokat @Implementation segítségével. Az egyedi shadow-ok a @Config(shadows = [CustomShadow::class]) segítségével regisztrálhatók.
A Robolectric támogatja a ContentProvider tesztelését a Robolectric.buildContentProvider() segítségével. Ellenőrizhetők a CRUD műveletek, a lekérdezések URI-egyeztetéssel és a hozzáférési jogosultságok kezelése. Az erőforrások (szövegek, színek, méretek) szintén elérhetők a RuntimeEnvironment.application.resources-on keresztül, lehetővé téve az erőforrásfüggő kód tesztelését.
Az instrumentációs tesztekről Robolectric-re való áttérés a megközelítés megváltoztatását igényli. Instrumentációs tesztek (AndroidJUnit4) a valós viselkedést ellenőrzik az emulátoron, Robolectric — az elkülönített logikát shadow-környezetben. Javasolt az üzleti logikát Robolectric tesztekkel lefedni, az instrumentációs teszteket pedig az integrációs forgatókönyvek számára megtartani.
Migrációkor: cserélje ki az AndroidJUnit4-et RobolectricTestRunner-re, adjon hozzá @Config-ot a cél SDK verzióval, cserélje ki az ActivityTestRule-t ActivityController-re, és helyezze át a függőségeket az androidTestImplementation-ből a testImplementation-be. Mock-ok (MockK, Mockito) változtatás nélkül működnek Robolectric-kel — nem függnek a platformtól.
A Robolectric nem támogatja: kamera (CameraX), NFC, Bluetooth, biometria, valós fájlokkal való munka és natív könyvtárak tesztelését. Ezekhez a forgatókönyvekhez instrumentációs tesztek szükségesek az emulátoron. A Robolectric nem reprodukálja a valós megjelenítést sem — a layout teszteket jobb Compose Test Rule-on vagy Espresso-n keresztül végezni. Az üzleti logika, navigáció és ViewModel állapotok ellenőrzéséhez azonban a Robolectric teljesen helyettesíti az emulátort 10-szeres gyorsítással.
A Robolectric JDK 11 vagy újabb verziót igényel, és kompatibilis az AGP-vel (Android Gradle Plugin) 7.0-tól a legutolsó stabil verzióig. A Robolectric SDK-kezelője automatikusan letölti a szükséges Android API verziókat az első indításkor — ez egyszeri művelet. CI-szerverekhez javasolt előre letölteni az SDK-t az sdkmanager-en keresztül a késések elkerülése érdekében az első tesztfuttatáskor. A Robolectric új verzióra frissítése általában nem igényel változtatásokat a tesztkódban, csak a függőségi szám frissítését a build.gradle-ben.
A Robolectric kompatibilis a népszerű mock-olási keretrendszerekkel: MockK Kotlinhoz és Mockito Java-hoz. A mock-ok a függőségek elkülönítésére szolgálnak: tárak, API-kliensek, SharedPreferences. A fő szabály — ne mock-oljon Android SDK osztályokat, ehhez shadow-objektumok állnak rendelkezésre. Csak az alkalmazás rétegeit mock-olja: UseCase, Repository, DataSource és az üzleti logika egyéb komponenseit. A shadow-objektumok és mock-ok ilyen kombinációja maximális rugalmasságot biztosít minimális tesztírási költséggel.
Gyakran Ismételt Kérdések
Az Espresso egy instrumentációs keretrendszer, amely emulátoron vagy eszközön fut. A Robolectric egy egységteszt-keretrendszer, amely a JVM-en működik. Az Espresso a valós viselkedést teszteli, a Robolectric — az elkülönített logikát shadow-környezetben. Kiegészítik egymást.
Igen, a Robolectric támogatja a Jetpack Compose-t a 4.8-as verziótól kezdve. A Compose komponensek tesztjei a ComposeTestRule segítségével végezhetők el, hasonlóan az emulátorhoz. A Compose tesztek a Robolectric-en azonban nem ellenőrzik a valós megjelenítést — csak a kompozíció logikáját.
A Robolectric támogatja a többmodulos projekteket. Minden modul külön konfigurálható a saját manifestjének és erőforrásainak megadásával. Az UI komponensek nélküli modulokhoz elegendő egy könyvtári modul android plugin nélkül. Nagy, több tucat modullal rendelkező projektekben az egyes modulok Robolectric tesztjei párhuzamosan futnak, ami további sebességelőnyt biztosít az emulátoron történő szekvenciális futtatáshoz képest.
Az erőforrásokkal kapcsolatos probléma akkor merül fel, ha a build.gradle-ben nincs megadva az unitTests.includeAndroidResources = true, vagy hiányzik a @Config annotáció a megfelelő manifest útvonallal. A Robolectric a build/intermediates könyvtárból származó lefordított erőforrásokat használja.
A Robolectric tesztek hétköznapi Java/Kotlin tesztekként debugolhatók az Android Studio-ban. Elérhetők a breakpoint-ok, a step-through debug, a shadow-objektumok és állapotuk ellenőrzése. A naplózás a -Drobolectric.logging=debug VM opciókon keresztül kapcsolható be.
Összefoglalás
Kulcsrakész mobilalkalmazást fejlesztünk
Az IT Sectr 2017 óta készít iOS és Android alkalmazásokat induló vállalkozásoknak és vállalkozásoknak. Tanácsot adunk, és a legjobb megoldást javasoljuk.
Olvassa el is