Mockito – adnotacje

Cześć drogi czytelniku 🙂 ! Dzisiejszy artykuł przeznaczyłam na opisanie adnotacji Mockito z freamworks Mockito z uwzględnieniem Junit4 i Junit5. Zanim jednak przejdę do tematu pozwolę sobie również polecić Ci bardzo dobry artykuł: Piramida, diament i trofeum – jak rozplanować testy automatyczne w aplikacji jak i cały blog Przemka Bykowskiego. Znajdziesz tam informacje na m.in na temat: testowania integracyjnego i E2E.

Aby móc skorzystać z adnotacji z Mockito należny nad klasą dodać dla Junit4: @RunWith(MockitoJUnitRunner.class) natomiast dla Junit5 jest to: @ExtendWith(MockitoExtension.class) i już można dodawać kolejne adnotacje. Dodatkowo biblioteka Mockito2 pozawala na zamieszczenie jeszcze jednej adnotacji nad klasą testową. Jest to: @MockitoSettings. Adnotacja ma do wyboru opcje strictness z której można wybrać klasę Strictness a z niej: LENIENT, STRICT_STUB lub WARN. W naszym przykładzie jest zastosowana pełna adnotacja: @MockitoSettings (strictness = Strictness.STRICT_STUBS) – ponieważ chodzi o zwiększenie restrykcyjności. Powinno pozwolić to na bardzo dokładne sprawdzenie tego w jaki sposób korzystamy z mocków i stubów w testach. Wpływa również na szybsze i lepsze wykrycie błędów. Domyślnie opcja ustawiona jest na WARN.

Należy zwrócić tutaj uwagę na fakt że jeżeli nad klasą mamy adnotacje @MockitoSettings to andotacja @ExtendWith nie jest już wymagana. Dzieje się tak dlatego że jest ona zawarta w @MockitoSettings. Proszę spójrz poniżej:

Źródło: Dokumetacja: package org.mockito.junit.jupiter;

Adnotacja @InjectMocks – określa w której klasie będą znajdować się zależności które w testach zamieniamy w mocki i których działanie będziemy chcieli programować lub weryfikować. W naszym przykładzie będzie to klasa UnitService ponieważ posiada zależność którą jest UnitRepository. I to UnitService oznaczamy adnotacją @InjectMock.

Natomiast adnotacja @Mock określa dany obiekt mockowy, i jest ona tożsama z metodą mock (o czym będzie poniżej). W naszym przykładzie mockowany będzie interfejs UnitRepository i to nad nim ustawiamy adnotacje @Mock. Zobaczmy jak wygląda taki przykład:

@MockitoSettings (strictness = Strictness.STRICT_STUBS)lub 
@RunWith(MockitoJUnitRunner.class)- JUnit4 lub  @ExtendWith(MockitoExtension.class)JUnit5
class UnitServiceTest {

@InjectMocks
private UnitService unitService; 

@Mock 
private UnitRepository unitRepository;

Dzięki tym adnotacją znacznie upraszczamy sobie kod jednak czy to dobrze? Adnotacje te niosą ze sobą pewne niebezpieczeństwa. Wyobraźmy sobie że nasza aplikacja jest rozbudowywana o nowe funkcjonalności w związku z czym do aplikacji dodajemy np: CargoRepository. Wyobraźmy sobie teraz że pisząc testy zapomnieliśmy dodać adnotacji @Mock tak jak poniżej.

Źródło: Archiwum własne. Testy i mock
Źródło: Przyzakładowy test dla przetestowania adnotacji @Mock i @InjectMock

Wówczas wynik przykładowego testu mówi “NullPointException” i rozpoczyna się debugowanie…

Źródło: Archiwum własne. Error przykładowego testu gdy zapomnimy o adnotacji @Mock

Zobaczmy teraz zachowanie testu gdy skorzystamy z metody mock. Jak widać na zdjęciu poniżej gdy tylko dodamy nowe CargoRepositry do Testu ale jeszcze nie zdążymy go “wstrzyknąć” do przykładowego UnitService od razu InteliJ cudownie podkreśli to przeoczenie na czerwono że coś jest nie tak.

Źródło: Archiwum własne. Źródło: Archiwum własne. Testy i metoda mock().

W takie sytuacji od razu dostajemy informacje że chodzi o konstruktor.

Źródło: Archiwum własne. Error przykładowego testu gdy korzystamy z metody mock() i nie dodamy zależności.

Jak więc widzisz drogi czytelniku adnotacje są wiele rzeczy ułatwiają jednak trzeba je stosować z rozmysłem aby nie spędzić zbyt wiele czasu na debugowaniu.

Zachęcam Cię również do innych moich artykułów na temat testowania i Moków np: Weryfikacja wywołań metod na Mockach

Jeśli uważasz powyższy tekst za pomocny, podziel się z kimś komu może być przydatny, na pewno będzie Ci wdzięczny. A tymczasem do zboczenia w kolejnym wpisie 🙂 🙂 !!

Leave a Comment

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *