Robolectric — co to jest, zasady działania i testy jednostkowe Android

Autor: IT Sectr Opublikowano: 2026-04-09 Czas czytania: 8 min

Robolectric to framework do testów jednostkowych aplikacji Android, który pozwala uruchamiać testy bezpośrednio na JVM bez emulatora lub fizycznego urządzenia. Przechwytuje wywołania Android SDK i dostarcza shadow-obiekty, emulujące zachowanie rzeczywistych komponentów. Według Robolectric Documentation, 2025, shadow-obiekty zastępują około 15 tysięcy klas Android API, zapewniając izolację testów od platformy.

Najważniejsze

  • Robolectric — framework do testów jednostkowych Android bez emulatora, działający na JVM
  • Shadow-obiekty przechwytują wywołania Android SDK i emulują zachowanie systemu
  • Integracja z JUnit 4 i 5 pozwala używać standardowych runnerów testowych
  • Testy wykonują się w sekundach, a nie minutach, jak w emulatorze
  • Wsparcie dla Jetpack Compose, fragmentów, intentów, ContentProvider i zasobów

Co to jest Robolectric

Robolectric to framework open-source, stworzony w 2010 roku w celu przyspieszenia testowania aplikacji Android. Zamiast uruchamiania na emulatorze lub urządzeniu, Robolectric dostarcza shadow-implementacje klas Android SDK, które działają bezpośrednio na wirtualnej maszynie Java (JVM). Pozwala to na wykonanie tysięcy testów w sekundy.

Problem, który rozwiązuje Robolectric

Tradycyjne testowanie Android wymaga uruchomienia aplikacji na emulatorze, co zajmuje 3–10 minut na budowę APK, instalację i uruchomienie. Robolectric eliminuje ten krok: testy są kompilowane jako zwykłe testy Java/Kotlin i uruchamiane przez JUnit. Daje to pętlę sprzężenia zwrotnego w kilka sekund zamiast minut.

Obsługiwane wersje Android

Robolectric obsługuje wszystkie wersje Android począwszy od API 16 (Android 4.1) aż do najnowszej stabilnej. Dla każdej wersji dostarczany jest odpowiedni zestaw shadow-obiektów, które emulują zachowanie właśnie tej wersji platformy, na której testowana jest aplikacja.

Architektura i shadow-obiekty

Architektura Robolectric opiera się na mechanizmie przechwytywania wywołań poprzez podmianę classloadera. Gdy test wywołuje metodę Android SDK, Robolectric przechwytuje wywołanie i kieruje je do shadow-obiektu. Shadow-obiekt to klasa Java, która imituje rzeczywiste zachowanie komponentu Android, ale działa bez natywnej platformy.

Jak działają shadow

Shadow-obiekty implementują kluczowe metody oryginalnych klas Android. Na przykład ShadowTextView imituje metody getText(), setText(), getCurrentTextColor() i inne. Po wywołaniu textView.setText("Hello") shadow zapisuje string i zwraca go przy wywołaniu getText(). Izoluje to testy od rzeczywistego renderowania i usług systemowych.

Shadow-hierarchia

Robolectric obsługuje ponad 200 shadow-klas, pokrywających główne komponenty Android SDK: Activity, Fragment, TextView, Button, RecyclerView, WebView, LocationManager, ConnectivityManager i wiele innych. Shadow-obiekty podążają za tą samą hierarchią dziedziczenia, co oryginalne klasy Android.

Instalacja i konfiguracja Robolectric

Instalacja Robolectric w projekcie Gradle wymaga dodania zależności testImplementation "org.robolectric:robolectric:4.x". Należy również określić konfigurację android:sdk w pliku build.gradle i dodać android:testInstrumentationRunner. Do pracy z Robolectric nie jest wymagany plugin android-testów.

Podstawowa konfiguracja Gradle

Po dodaniu zależności trzeba skonfigurować katalog dla manifestu, zasobów i assetów. Robolectric automatycznie znajduje AndroidManifest.xml, ale może być konieczne ręczne wskazanie ścieżki przez adnotację @Config lub właściwości systemowe. Dla projektów wielomodułowych konfigurację ustawia się osobno dla każdego modułu.

groovy
// build.gradle — konfiguracja 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'
}

Adnotacja @Config

Adnotacja @Config pozwala nadpisać parametry testu: sdk (wersja API), manifest (ścieżka do manifestu), qualifiers (konfiguracja ekranu, język). Jest to przydatne do testowania zachowania aplikacji na różnych wersjach Android, orientacjach ekranu i lokalizacjach.

Pisanie testów z Robolectric

Testy Robolectric pisze się jako zwykłe testy jednostkowe z @RunWith(RobolectricTestRunner.class) dla JUnit 4 lub przez RobolectricExtension dla JUnit 5. ActivityController zarządza cyklem życia Activity: create(), start(), resume(), pause(), stop(), destroy(). Pozwala to szczegółowo testować każde przejście stanu.

Testowanie Activity

Do testowania Activity używa się ActivityController, który sekwencyjnie przechodzi przez etapy cyklu życia. Dostęp do Activity odbywa się przez controller.get(). Wszystkie komponenty widoku są dostępne przez findViewById, jak w rzeczywistej aplikacji. Shadow-obiekty pozwalają sprawdzić teksty, widoczność, kolory i inne atrybuty widoku.

java
@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());
    }
}

Testowanie intentów i nawigacji

Robolectric przechwytuje wywołania startActivity() i pozwala sprawdzić wysłane intenty przez ShadowActivity. Daje to możliwość testowania nawigacji: sprawdzenia, że po kliknięciu przycisku wysyłany jest Intent z prawidłowym Action, Data i parametrami Extra.

java
@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 a emulator

Robolectric i emulator rozwiązują różne zadania. Robolectric jest idealny do szybkich testów jednostkowych, sprawdzania logiki UI, komponentów biznesowych i repozytoriów. Emulator jest niezbędny do testów instrumentalnych, sprawdzania integracji z API, testowania kamery, czujników i wydajności.

CechaRobolectricEmulator
Prędkość~5 sek na 100 testów~5 min na 100 testów
UruchomienieBez budowy APKWymaga budowy APK
Rzeczywiste APIShadow-emulacjaNatywny Android SDK
Out-of-the-boxTylko JUnitDowolne frameworki

Testowanie ViewModel i Repository

Robolectric doskonale nadaje się do testowania ViewModel, Repository i UseCase — komponentów, które używają Android SDK, ale nie wymagają rzeczywistego UI. ViewModel testuje się przez zwykły test JUnit z RobolectricExtension, przy czym komponenty cyklu życia (LiveData, StateFlow) działają w shadow-środowisku bez mocków.

Testowanie LiveData

Robolectric obsługuje LiveData od razu po wyjęciu z pudełka: można zasubskrybować LiveData w teście, zmienić stan przez ViewModel i sprawdzić wyemitowaną wartość. Do operacji asynchronicznych używa się InstantTaskExecutorRule lub runBlocking dla korutyn. Eliminuje to konieczność mockowania komponentów architektonicznych.

kotlin
@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)
    }
}

Niestandardowe shadow-obiekty

Jeśli standardowe shadow-obiekty Robolectric nie pokrywają potrzebnej klasy Android SDK, można stworzyć niestandardowy Shadow. W tym celu tworzy się klasę z adnotacją @Implements(ClassName.class) i implementuje potrzebne metody z @Implementation. Niestandardowe shadow rejestruje się przez @Config(shadows = [CustomShadow::class]).

Testowanie ContentProvider i Resources

Robolectric obsługuje testowanie ContentProvider przez Robolectric.buildContentProvider(). Można sprawdzić operacje CRUD, query z dopasowaniem URI i obsługę uprawnień. Zasoby (stringi, kolory, rozmiary) są również dostępne przez RuntimeEnvironment.application.resources, co pozwala testować kod zależny od zasobów.

Migracja z emulatora na Robolectric

Przejście z testów instrumentalnych na Robolectric wymaga zmiany podejścia. Testy instrumentalne (AndroidJUnit4) sprawdzają rzeczywiste zachowanie na emulatorze, Robolectric — izolowaną logikę w shadow-środowisku. Zaleca się pokrywać testami Robolectric logikę biznesową, a testy instrumentalne pozostawić dla scenariuszy integracyjnych.

Adaptacja istniejących testów

Podczas migracji należy: zastąpić AndroidJUnit4 na RobolectricTestRunner, dodać @Config z docelową wersją SDK, zastąpić ActivityTestRule na ActivityController i przenieść zależności z androidTestImplementation do testImplementation. Mocki (MockK, Mockito) działają z Robolectric bez zmian — nie zależą od platformy.

Ograniczenia podczas migracji

Robolectric nie obsługuje: testowania kamery (CameraX), NFC, Bluetooth, biometrii, pracy z rzeczywistymi plikami i bibliotekami natywnymi. Dla tych scenariuszy konieczne są testy instrumentalne na emulatorze. Robolectric nie odtwarza również rzeczywistego renderowania — testy układu lepiej wykonywać przez Compose Test Rule lub Espresso. Jednak do sprawdzania logiki biznesowej, nawigacji i stanów ViewModel Robolectric całkowicie zastępuje emulator z 10-krotnym przyspieszeniem przebiegu testów.

Zgodność z wersjami Java i Kotlin

Robolectric wymaga JDK 11 lub nowszego i jest zgodny z AGP (Android Gradle Plugin) od 7.0 do najnowszej stabilnej wersji. Menedżer SDK Robolectric automatycznie pobiera wymagane wersje Android API przy pierwszym uruchomieniu — to jednorazowa operacja. Dla serwerów CI zaleca się wcześniejsze pobranie SDK przez sdkmanager, aby uniknąć opóźnień przy pierwszym uruchomieniu testów. Aktualizacja Robolectric do nowszej wersji zwykle nie wymaga zmian w kodzie testów, tylko aktualizacji numeru zależności w build.gradle.

Integracja z MockK i Mockito

Robolectric jest zgodny z popularnymi frameworkami mockującymi: MockK dla Kotlin i Mockito dla Java. Mocki są używane do izolacji zależności: repozytoriów, klientów API, SharedPreferences. Główna zasada — nie mockować klas Android SDK, do tego służą shadow-obiekty. Mockuj tylko warstwy aplikacji: UseCase, Repository, DataSource i inne komponenty logiki biznesowej. Taka kombinacja shadow-obiektów i mocków daje maksymalną elastyczność przy minimalnych kosztach pisania testów.

Często zadawane pytania

Czym różni się Robolectric od Espresso?

Espresso to instrumentalny framework, uruchamiany na emulatorze lub urządzeniu. Robolectric to framework jednostkowy, działający na JVM. Espresso testuje rzeczywiste zachowanie, Robolectric — izolowaną logikę w shadow-środowisku. Uzupełniają się nawzajem.

Czy można testować Jetpack Compose z Robolectric?

Tak, Robolectric obsługuje Jetpack Compose od wersji 4.8. Testy komponentów Compose są wykonywane za pomocą ComposeTestRule, podobnie jak w emulatorze. Testy Compose na Robolectric nie sprawdzają jednak rzeczywistego renderowania — tylko logikę kompozycji.

Jak Robolectric działa z modułami Gradle?

Robolectric obsługuje projekty wielomodułowe. Każdy moduł konfiguruje się osobno z określeniem własnego manifestu i zasobów. Dla modułów bez komponentów UI wystarczy moduł biblioteczny bez pluginu android. W dużych projektach z dziesiątkami modułów testy Robolectric każdego modułu uruchamiają się równolegle, co daje dodatkowy zysk prędkości w porównaniu z sekwencyjnym uruchomieniem na emulatorze.

Dlaczego Robolectric może nie znaleźć zasobów?

Problem z zasobami występuje, jeśli w build.gradle nie określono unitTests.includeAndroidResources = true lub brakuje adnotacji @Config z prawidłową ścieżką do manifestu. Robolectric używa skompilowanych zasobów z build/intermediates.

Jak debugować testy Robolectric?

Testy Robolectric debuguje się jak zwykłe testy Java/Kotlin w Android Studio. Dostępne są breakpoint, step-through debug, inspekcja shadow-obiektów i ich stanu. Logowanie włącza się przez -Drobolectric.logging=debug w opcjach VM.

Podsumowanie

  • Robolectric — framework do szybkich testów jednostkowych Android na JVM bez emulatora
  • Shadow-obiekty zastępują ponad 200 klas Android SDK, emulując ich zachowanie
  • Cykl życia Activity i Fragment jest zarządzany przez ActivityController z możliwością sprawdzania stanów
  • Testowanie intentów przez ShadowActivity pozwala sprawdzać nawigację i przekazywanie danych
  • Integracja z JUnit i Gradle nie wymaga dodatkowych runnerów instrumentalnych
  • Adnotacja @Config określa wersję API, język, konfigurację ekranu i zasoby
  • Robolectric i Espresso uzupełniają się: szybkie testy jednostkowe versus instrumentalne

Opracujemy aplikację mobilną pod klucz

IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.

Omów projekt

Przeczytaj również