Testy jednostkowe rzadko kiedy dotyczą jednostki testowej wolnej od zależności innych obiektów co w konsekwencji prowadzi do definicji problemu tworzenia niezależnych testów na których rezultat nie ma wpływu żadna zależność testowanej jednostki. Wymaganą prawdziwą zależność można czasami dostarczyć ręcznie jednakże jest to kosztowne, obarczone marginesem błędu oraz często niewykonalne (szczególnie w przypadku testów instrumentalnych). Alternatywą dla tworzenia prawdziwych zależności jest dostarczanie dublerów (double test), które można sklasyfikować ze względu na przeznaczenie. Jedna z wielu definicji wyróżnia m.in. następujące obiekty: dummy, fake, stub i mock. Dummy jest przekazywany w celu spełnienia założeń sygnatury jednak jego metody nie są wywoływane. Fake posiada uproszczoną działającą implementacje spełniającą założenia interakcji. Stub dostarcza minimalną implementacją zależności, która pomija proces obliczeniowy i bezpośrednio zwraca zdefiniowany rezultat w taki sposób, aby test wykonał się pozytywnie. Natomiast mock to naiwna implementacja zależności, która bierze udział w procesie testowania i rejestruje nawiązane z nią interakcje, przeznaczona do badania zachowania. Mnogość definicji podziału dublerów oraz wynikające z tego różnice są powodem wielu niejasności, a sama terminologia jest mało istotna w procesie tworzenia zastępników. Pozwala on jednak zrozumieć co dokładnie i w jaki sposób ma zostać przetestowane. Mockito jest frameworkiem wspomagającym pisanie testów jednostkowych poprzez dostarczanie dublerów, które dzieli na zwyczajne Mock oraz częściowe Spy.
Przykład Na podstawie poniższych klas Manager oraz Data zostaną przedstawione cechy i właściwości zarządzania naiwnymi implementacjami w Mockito.
Tworzenie
Obiekt zastępnika oznaczony adnotacją @Mock lub @Spy może zostać inicjalizowany na kilka sposobów, m.in. poprzez uruchomienie klasy z użyciem @RunWith(MockitoJUnitRunner.class), wykorzystanie zasady MockitoJUnit.rule() lub manualną inicjalizację za pomocą metody MockitoAnnotations.initMocks(). Instancję atrapy można uzyskać statyczną metodą mock() lub spy() co pozwala na pominięcie adnotacji.
Obiekty dublerów w Mockito mogą zostać stworzone tylko dla typów własnych. Nie można zatem dostarczyć imitacji prymitywów. Co więcej należy przestrzegać zasady, że imitacji podlegają zależności testowanej jednostki, a nie sam testowany obiekt. Adnotacja @InjectMocks automatycznie wstrzykuje imitacje pól oznaczonych jako @Mock lub @Spy do obiektu co jest wykorzystywane jako alternatywa dla konstruktora w sytuacji tworzenia testowanej jednostki zależnej od innych atrap.
Mock i Spy
Mockito wprowadza podział zastępników na zwyczajne (Mock) oraz częściowe (Spy). Mock nie tworzy faktycznej instancji lecz obiekt klasy szkieletowej co pozwala w całości na imitacje wykonania metod klasy bez wpływu na strukturę atrapy. Spy tworzy realną instancje klasy przez co wywołuje faktyczną implementację obiektu dla wszystkich zachowań dla których nie została zdefiniowana naiwna implementacja zachowując przy tym właściwości atrapy (weryfikacja i imitacja).
Konfiguracja
Atrapy mogą być konfigurowane w taki sposób, aby zwracały zadaną wartość w zależności od metody i argumentów. W tym celu należy zdefiniować naiwną implementację m.in. za pomocą instrukcji when.thenReturn czy doReturn.when. Różnica między nimi polega na tym, że when.thenReturn sprawdza typy w trakcie kompilacji, pozwala na zwracanie wielu wartości i w gruncie rzeczy wykonuje wywołaną metodę co w konsekwencji może prowadzić do rzucenia wyjątku. Natomiast doReturn.when wspiera obiekty opakowań (wrapper) oznaczone jako @Spy i metody nie zwracające wartości oraz eliminuje problem wielu argumentów.
Dla bardziej złożonych zapytań dla których oczekiwany rezultat nie jest jawny lub zależnych od argumentów można wykorzystać instrukcję thenAnswer lub doAnswer.
Weryfikacja
Mockito przechowuje informacje na temat wszystkich wywołań metod wraz z użytymi argumentami. Dzięki temu pozwala na śledzenie działalności atrap oraz weryfikację ich wywołań za pomocą funkcji verify(). Aby uzyskać informacje nt argumentów wywołań funkcji należy wykorzystać ArgumentCaptor.
PowerMock
Tworzenie imitacji w Mockito jest obarczone pewnymi ograniczeniami. Niemożliwym jest tworzenie naiwnej implementacji dla statycznych i prywatnych metod klasy czy wywołań konstruktora. Aby temu zaradzić można wykorzystać bibliotekę PowerMock, której zależności pakietów mogą zawierać implementacje JUnit oraz Mockito dzięki czemu zachowana jest zgodność wersji. Klasa testowa korzystająca z PowerMock powinna być uruchamiana z instrukcją @RunWith(PowerMockRunner.class) wraz z adnotacją dla klasy testowanej @PrepareForTest(ClassName.class). PowerMock uzupełnia implementacje Mockito o dodatkowe metody realizacji atrap dla metod statycznych, prywatnych i konstruktorów takie jak np.: mockStatic, verifyPrivate, whenNew.
Jako alternatywę dla Mockito i PowerMock w Kotlin warto rozważyć bibliotekę Mockk, która rozwiązuje problemy występujące w Mockito i wspiera natywne cechy Kotlin takie jak np.: rozszerzenia. Framework Robolectric umożliwi natomiast przeprowadzanie w łatwy sposób lokalnych testów jednostkowych zależnych od Android SDK.