Kiedy @Mock, a kiedy @Autowired w JUnit

Odpowiedz Nowy wątek
2017-12-23 23:41
1

J/w, przerabiam sobie jakieś tam przykładowe testy jednostkowe z kursu na Udemy i raz gościu używa @Mock, raz @Autowired. Istnieje jakaś wskazówka kiedy używać jednej adnotacji, a kiedy drugiej ? Wiem jaka jest różnica w działaniu między jedną a drugą, ale jest jakaś zasada, że np do repozytoriów dajemy @Autowired czy od czego innego to zależy ?

edytowany 2x, ostatnio: slayer9, 2017-12-23 23:45

Pozostało 580 znaków

2017-12-24 00:02
2

Skoro zadajesz takie pytanie to na 100% nie rozumiesz jaka jest różnica i co te adnotacje oznaczają. Ja generalnie zalecam w ogóle nie wstrzykiwać przez pola tylko przez konstruktor i nagle ten problem w ogóle znika.


Masz problem? Pisz na forum, nie do mnie. Nie masz problemów? Kup komputer...
@Mock symuluje obiekt, tworzy jego atrapę, a @Autowired wstrzykuje beana z kontenera IoC ? - slayer9 2017-12-24 00:12
Nie, nie do końca. @Mock wstrzykuje mocka tam gdzie w zwykłej klasie zarządzanej przez IoC masz jakieś @Inject albo @Autowired. To taki workaround kiedy wstrzykujesz coś przez pole i nie masz ani konstruktora ani settera żeby w teście ustawić mockowaną zależność. - Shalom 2017-12-24 00:37
@Shalom chyba pomyliłeś @Mock z @InjectMocks - nie100sowny 2017-12-24 00:46
@nie100sowny: wyobraź sobie że Mockito to nie jedyna biblioteka do mockowania. @Mock z Easymocka działa tak jak napisałem. - Shalom 2017-12-24 02:28

Pozostało 580 znaków

2017-12-24 00:36
2

Koledze chodzi chyba bardziej, że w testach widzi te dwa typy adnotacji i nie wie o co chodzi :D

Adnotacja @Mock to adnotacja biblioteki Mockito. Powoduje ona, że pole nią oznaczone będzie zawierało mock stworzony przez Mockito.
Do działania wymaga @RunWith(MockitoJUnitRunner.class) lub wywołania MockitoAnnotations.initMocks(this);

Adnotacja @Autowired to adnotacja Spring Framework. Powoduje, że pole nią oznaczone będzie zawierało obiekt danego typu wstrzyknięty z kontekstu Springa.
Do działania wymaga @RunWith(SpringRunner.class).
Czyli to działa tylko w przypadku testów integracyjnych, gdzie mamy cały kontekst Springa postawiony.

Przykład w Spring Boot i Spring Data:
Testujesz klasę UsersService, która potrzebuje UsersRepository do działania.

Gdy w teście wykorzystasz @Mock to repozytorium będzie mockiem i będziesz musiał / mógł zaprogramować jego zachowanie. Test nie wymaga innych klas i kontekstu Springa, czyli jest jednostkowy.

Gdy w teście wykorzystasz @Autowired to repozytorium będzie prawdziwym repozytorium do bazy lub do testowej bazy w pamięci H2 (zależnie co tam w kontekście Springa sobie ustawiłeś). Takie test jest raczej testem integracyjnym.

Zalecenia:

  1. Zgodnie z piramidą testów preferujemy testy jednostkowe, są szybkie i bardziej niezależne od różnych magii frameworków / środowisk.
  2. W przypadku jednak Repozytoriów mockowanie ma mały sens, bo tak naprawdę piszesz testy dla Mockito. Repozytoria testujemy integracyjnie

Ciekawostka na forum mamy takich userów: @Mock i @Autowired


"Gdy się nie wie, co się robi, to się dzieją takie rzeczy, że się nie wie, co się dzieje"


edytowany 6x, ostatnio: nie100sowny, 2017-12-24 00:42
Adnotakcja "@Mock" niekoniecznie musi pochodzić z biblioteki Mockito, równie dobrze może być z EasyMock. - greek96 2018-05-01 10:54

Pozostało 580 znaków

2017-12-24 01:02
0

Dzięki. A kiedy używamy @Autowired nad jakimś repozytorium to możemy wtedy używać metody when()thenReturn() ? Pozmieniałem trochę w kodzie, żeby pole pod @Autowired nie było nullem i dostałem error Misplaced or misused argument matcher detected here, akurat w linijce z tą metodą.

edytowany 2x, ostatnio: slayer9, 2017-12-24 01:06

Pozostało 580 znaków

2017-12-24 02:35
1

Adnotacja @Mock to adnotacja biblioteki Mockito. Powoduje ona, że pole nią oznaczone będzie zawierało mock stworzony przez Mockito.

Bzdura. Inne biblioteki, jak EasyMock, także wspierają taką adnotacje.

Gdy w teście wykorzystasz @Autowired to repozytorium będzie prawdziwym repozytorium do bazy lub do testowej bazy w pamięci H2 (zależnie co tam w kontekście Springa sobie ustawiłeś). Takie test jest raczej testem integracyjnym.

Tylko o ile skonfigurujesz jakiś testowy kontekst. Inaczej guzik się tam wstrzyknie.

Zgodnie z piramidą testów preferujemy testy jednostkowe, są szybkie i bardziej niezależne od różnych magii frameworków / środowisk.

To żart? Testy integracyjne są równie ważne jak jednostkowe. Jest ich mniej, z definicji, ale ich brak to spory błąd. Tak tu tylko zostawie:

Teraz tak zupełnie serio:

  1. @Inject a nie @Autowired!
  2. Wstrzykiwanie przez konstruktor a nie przez pola! Wtedy problem w ogóle znika bo nie trzeba cudować z dodatkowymi adnotacjami ani specjalnymi runnerami dla testów. Tworzysz obiekt i musisz mu podać argumenty. Jak podasz realne obiekty to będą realne obiekty, jak mocki to będą mocki. Jeśli ktoś uważa że jest inaczej, to zalecam spróbować sobie wstrzyknąć do testowanego beana kilka stubów zaimplementowanych "ręcznie" zamiast konfigurowalnych mocków oraz kilka realnych obiektów. Przy field injection trudno to wykonać.

Masz problem? Pisz na forum, nie do mnie. Nie masz problemów? Kup komputer...

Pozostało 580 znaków

2017-12-24 14:08
0

Ponawiam pytanie, czy metoda when() jest tylko dla mocków ?

Pozostało 580 znaków

2017-12-24 15:34
1

Tak.


Masz problem? Pisz na forum, nie do mnie. Nie masz problemów? Kup komputer...
ha ! nieprawda, jak sobie w moim serwisie zrobię metodę when() to mogę użyć na produkcyjnym kodzie - szach mat ! a tak naprawdę to nie mogę, bo w html'u nie ma metod :/ - rubaszny_karp 2017-12-24 18:19

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0