Mockito w testach jednostkowych: Matchers, wyjątki i ArgumentCaptor.

Cześć drogi czytelniku 🙂 ! Dzisiejszy artykuł przeznaczyłam na opisanie Mockito w testach jednostkowych. Skupiałam się tutaj na podstawowych funkcjonalnościach takich jak: Matchers, wyjątki i ArgumentCaptor.

1. Machers

Argument Matchers wykorzystywane są gdy chcemy przetestować metodę ale nie wiemy z jakim argumentem. I tak np. kontynuując przykład z wpisu: Weryfikacja wywołań metod na Mockach sprawdzenie czy metoda canHandleCart zostanie wywołana z parametrem cart:

given(cartHandler.canHandleCart(cart)).willReturn(true);

może zostać zapisana z wykorzystaniem matcher’a „any” który przejmuje każdą wartość. Wówczas zapis będzie wyglądał następująco:

 given(cartHandler.canHandleCart(any())).willReturn(true);

Współpracując z tym Matcher’em metodę tą możemy zapisać również w następujący sposób:

given(cartHandler.canHandleCart(any(Cart.class))).willReturn(true);

– dzięki temu że matchers „any” sprecyzowaliśmy o wartość klasy Cart – any będzie precyzowało tylko argumenty klasy Cart.

Dobre praktyki jednak mówią iż jeżeli jest to tylko możliwe używać matchersów danego typu. Więc jeśli gdzieś jest wymagany int najlepiej zastosować anyInt(). Z matchersów możemy także korzystać z wykorzystaniem metody verify oraz then.should() np.:

verify(cartHandler, atLeastOnce()).sendToPrepare(any(Cart.class));

W sytuacji gdy metoda składa się z kilku parametrów to decydując się na wykorzystanie matchersów powinniśmy konsekwentnie w ten sposób zdefiniować każdy parametr.

Warto również wiedzieć że metoda given().willReturn() możne przyjmować kilka parametrów.:

given(cartHandler.canHandleCart(cart)).willReturn(true, false); 
//then
assertThat(cartHandler.canHandleCart(cart), equalTo(true));
assertThat(cartHandler.canHandleCart(cart), equalTo(false));

Również w miejscu matchera możemy skorzystać z wyrażeń lambda w miejscu wartości lub matchera. Wykorzystujemy do tego metodę boolean argThat, która znajduje się w klasie ArgumentMatchers w bibliotece Mockito.

given(cartHandler.canHandleCart(argThat(c -> cart.getOrders().size > 0))).willReturn(true,false);

2. Wyjątki

Natomiast aby przetestować możliwość generowania wyjątków przez naszą metodę korzystając z metody testowej given() zamiast willReturn() korzystamy z willThrow(): i sprawdzamy asercją assertThrow.

given(cartHandler.canHandleCart(cart)).willThrow(IllegalStateException.class);
assertThrow(IllegalStateException.class, () -> cartService.processCart(cart));

3. Argument Captor

ArgumentCaptor służy do sprawdzenia z jakimi argumentami została wywołana dana metoda.

ArgumentCaptor<określamy jakiego typu bedzie argument>  argumentCaptor = ArgumentCaptor.forClass(Cart.class);
Dla naszego przykładu Cart będzie to więc wyglądać następująco: 
ArgumentCaptor argumentCaptor = ArgumentCaptor.forClass(Cart.class); 

Przechwycenie argumentu dzieje się w momencie weryfikacji danej metody gdy korzystamy z then.Should() lub z metody verify.

then(cartHandler).should().sendToPrepare(argumentCaptor
.capture()); 
verify(cartHandler).should().sendToPrepare(argumentCaptor
.capture());  

ArgumentCaptorem możemy sprawdzić np wielkość listy w obiekcie. Wykorzystujemy do tego metodę getValue() która dotyczy tylko jednego argumentu. Natomiast za pomocą metody getAllValues() pobieramy wszystkie argumenty danej listy.

assertThat(argumentCaptor.getValue().getOrders().size(), equalTo(1)); 
assertThat(argumentCaptor.getAllValues().size(),equalTo(2));  
assetThat(argumentCaptor.getAllValues().get(0).getOrders().size(), equalTo(1);  

4. Podsumowanie

Wykorzystanie biblioteki Mockito w testach jednostkowych daje nam spore możliwości w przeprowadzaniu testów. Na zakończenie zapraszam Cię drogi czytelniku do kolejnych artykułów na temat testów np: Weryfikacja wywołań metod na Mockach oraz do  artykułu: „Piramida, diament i trofeum – jak rozplanować testy automatyczne w aplikacji”Przemka Bykowskiego. Znajdziesz tam informacje na temat testów jednostkowych, integracyjnych oraz E2E 🙂 .

1 thought on “Mockito w testach jednostkowych: Matchers, wyjątki i ArgumentCaptor.”

  1. Czy jeśli w zamiast Captor użyłbym czegoś takiego:
    then(cartHandler).should().sendToPrepare(cart);
    to byłby to błąd?

Leave a Comment

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *