Uruchamianie jednostkowych testów instrumentalnych na urządzeniu lub emulatorze jest kosztowne i powolne. Jednakże w wielu sytuacjach nie sposób uciec od testowania logiki kodu powiązanego z komponentami Androida co sprawia, że testy instrumentalne są stosowane pomimo wynikających kosztów. Alternatywnym sposobem testowania kodu zależnego od Android SDK może być użycie framework Robolectric, który umożliwia przeprowadzanie lokalnych testów jednostkowych w środowisku wykonawyczm JVM na komponentach Android takich jak m.in. Activity, Fragment, Intent, Service czy ContentProvider. W przeciwieństwie do testów instrumentalnych Robolectric wykonuje się piaskownicy systemowej (sandbox) co pozwala na konfiguracje środowiska Android dla wszystkich testów. Robolectric dostarcza również dublerów komponentów Android dla których nie potrafi dokonać tłumaczenia do testów jednostkowych (np. sensory hardware, usługi systemowe). Obsługuje inflację widoków, ładowanie zasobów i wiele innych aspektów zaimplementowanych w natywnym kodzie na urządzeniach co pozwala na wykonanie większości czynności tak jak na prawidzwym urządzeniu. Robolectric w łatwy sposób pozwala na zapewnienie własnej implementacji wybranych metod Android SDK dzięki czemu możliwa jest np. symulacja warunków czy zachowań sensorów. Wykorzystanie Robolectric jest bliższe podejściu testowania czarnoskrzynkowego (skupionego na zachowaniu) i nie wyklucza jednoczesnego stosowania innych bibliotek naiwnych implementacji takich jak np. Mockito.
Przykład Na podstawie Aktywności MainActivity zostaną przedstawione możliwości implementacji testów jednostkowych w Robolectric.
Uruchomienie
Aby uruchomić test w Robolectric należy opatrzeć klasę testową adnotacją @RunWith(RobolectricTestRunner.class) oraz uzyskać instancję żądanej klasy komponentu.
Konfiguracja
Aby zmienić domyślną konfiguracje testów należy oznaczyć klasy lub metody adnotacją @Config wraz z deklaracją konfiguracji. Metody z adnotacją @Config nadpisują zachowanie z poziomu klasy. Konfiguracji mogą podlegać m.in. poziom sdk, plik manifest, klasy shadows, ścieżki do zasobów czy kwalifikatory (np. języka, regionu itp).
Cykl życia
ActivityController odpowiada za tworzenie oraz zarządzanie cyklem życia tworzonej Aktywności. Metoda buildActivity tworzy instancję ActivityController, która umożliwia wywołanie wybranych metod cyklu życia (create, start, resume, pause, stop, destroy) oraz pobranie instancji Aktywności dla bieżącego stanu. Aby bezpośrednio uzyskać obiekt Aktywności z przebytym pełnym cyklem tworzenia należy wywołać metodę setupActivity.
W analogiczny sposób można zarządzać innymi kompontentami Androida i ich cyklem życia poprzez operowanie na dedykowanym kontrolerze (ServiceController, FragmentController, ContentProviderController itp.) oraz wykonanie metod odpowiadających ich cyklowi życia.
Shadow
Robolectric tworzy środowisko wykonawcze zawierające prawdziwy kod Android SDK co zwiększa realizm testów tak jakby były przeprowadzane na fizycznym urządzeniu. Wszystkie klasy Android są zastąpione tzw. obiektami cienia (Shadows). Każdy obiekt cienia może modyfikować lub rozszerzać zachowanie odpowiadającej mu klasy z Android SDK. Aby stworzyć klasę Shadow należy oznaczyć ją adnotacją @Implements wraz z nazwą odpowiadającej klasy Android, opcjonalnie rozszerzyć superklasę Shadow oraz dostarczyć publiczny bez argumentowy konstruktor. Metody rozszerzene muszą mieć adnotację @Implementation (obiekt cienia implementuje metody z tą samą sygnaturą dla odpowiadającej klasy Android niezależnie od modyfikatora dostępu) i przeważnie modyfikator protected. Metoda directlyOn pozwala na wywołanie akcji na faktycznym obiekcie.
Klasa testowa lub metoda wykorzystująca własną implementacje klas Shadows musi być oznaczona adnotacją @Config(shadows=arrayOf(CustomShadowClass::class)) (lub zawierać odpowiedni wpis w pliku ustawień) co umożliwia rozpoznanie i skojarzenie klas Shadow z klasami przykrywanymi. Metoda shadowOf jest przeznaczona dla dostarczonych przez Robolectric klas Shadow, natomiast extract dla autorskich klas Shadow.