Komme i gang med Mockito @Mock, @Spy, @Captor og @InjectMocks
1. Oversikt
I denne opplæringen vil vi dekke kommentarene til Mockito-biblioteket – @Håne, @Spion, @Captor, og @InjectMocks.
For mer Mockito godhet, ta en titt på serien her.
2. Aktiver Mockito-merknader
Før vi går videre, la oss utforske forskjellige måter å muliggjøre bruk av merknader med Mockito-tester.
2.1. MockitoJUnitRunner
Det første alternativet vi har er å kommentere JUnit-testen med en MockitoJUnitRunner som i følgende eksempel:
@RunWith (MockitoJUnitRunner.class) offentlig klasse MockitoAnnotationTest {...}
2.2. MockitoAnnotations.initMocks ()
Alternativt kan vi aktivere Mockito-merknader programmatisk også ved å påkalle MockitoAnnotations.initMocks ():
@Før offentlig ugyldig init () {MockitoAnnotations.initMocks (dette); }
2.3. MockitoJUnit.rule ()
Til slutt, vi kan bruke en MockitoJUnit.rule ()som vist under:
offentlig klasse MockitoInitWithMockitoJUnitRuleUnitTest {@Rule offentlig MockitoRule initRule = MockitoJUnit.rule (); ...}
I dette tilfellet må vi huske å lage vår regel offentlig.
3. @Håne Kommentar
Den mest brukte kommentaren i Mockito er @Håne. Vi kan bruke @Håne for å opprette og injisere spottede forekomster uten å måtte ringe Mockito.mock manuelt.
I det følgende eksemplet - lager vi en hånet ArrayList med den manuelle måten uten bruk @Håne kommentar:
@Test offentlig ugyldig nårNotUseMockAnnotation_thenCorrect () {List mockList = Mockito.mock (ArrayList.class); mockList.add ("en"); Mockito.verify (mockList) .add ("one"); assertEquals (0, mockList.size ()); Mockito.when (mockList.size ()). ThenReturn (100); assertEquals (100, mockList.size ()); }
Og nå gjør vi det samme, men vi injiserer spottet ved hjelp av @Håne kommentar:
@Mock List mockedList; @Test offentlig ugyldig nårUseMockAnnotation_thenMockIsInjected () {mockedList.add ("one"); Mockito.verify (mockedList) .add ("one"); assertEquals (0, mockedList.size ()); Mockito.when (mockedList.size ()). ThenReturn (100); assertEquals (100, mockedList.size ()); }
Legg merke til hvordan - i begge eksemplene samhandler vi med mocken og verifiserer noen av disse interaksjonene - bare for å være sikker på at mocken oppfører seg riktig.
4. @Spion Kommentar
Nå - la oss se hvordan du bruker @Spion kommentar for å spionere på en eksisterende forekomst.
I det følgende eksemplet - lager vi en spion av en Liste med den gamle måten uten bruk @Spion kommentar:
@Test offentlig ugyldig nårNotUseSpyAnnotation_thenCorrect () {List spyList = Mockito.spy (new ArrayList ()); spyList.add ("en"); spyList.add ("to"); Mockito.verify (spyList) .add ("one"); Mockito.verify (spyList) .add ("to"); assertEquals (2, spyList.size ()); Mockito.doReturn (100) .when (spyList) .størrelse (); assertEquals (100, spyList.size ()); }
La oss nå gjøre det samme - spionere på listen - men gjør det ved å bruke @Spion kommentar:
@Spy List spiedList = ny ArrayList (); @Test offentlig ugyldig nårUseSpyAnnotation_thenSpyIsInjectedCorrectly () {spiedList.add ("one"); spiedList.add ("to"); Mockito.verify (spiedList) .add ("one"); Mockito.verify (spiedList) .add ("to"); assertEquals (2, spiedList.size ()); Mockito.doReturn (100) .when (spiedList) .størrelse (); assertEquals (100, spiedList.size ()); }
Legg merke til hvordan vi, som før, kommuniserer med spionen her for å sikre at den oppfører seg riktig. I dette eksemplet:
- Brukte ekte metode spiedList.add () for å legge til elementer i spiedList.
- Stubbet metoden spiedList.size () å returnere 100 i stedet for 2 ved hjelp av Mockito.doReturn ().
5. @Captor Kommentar
Neste - la oss se hvordan du bruker @Captor kommentar for å lage en ArgumentCaptor forekomst.
I det følgende eksemplet - lager vi en ArgumentCaptor med den gamle måten uten å bruke @Captor kommentar:
@Test offentlig ugyldig nårNotUseCaptorAnnotation_thenCorrect () {List mockList = Mockito.mock (List.class); ArgumentCaptor arg = ArgumentCaptor.forClass (String.class); mockList.add ("en"); Mockito.verify (mockList) .add (arg.capture ()); assertEquals ("one", arg.getValue ()); }
La oss nå benytte seg av @Captorfor samme formål - å skape en ArgumentCaptor forekomst:
@Mock List mockedList; @Captor ArgumentCaptor argCaptor; @Test offentlig ugyldig nårUseCaptorAnnotation_thenTheSam () {mockedList.add ("one"); Mockito.verify (mockedList) .add (argCaptor.capture ()); assertEquals ("one", argCaptor.getValue ()); }
Legg merke til hvordan testen blir enklere og mer lesbar når vi tar ut konfigurasjonslogikken.
6. @InjectMocks Kommentar
La oss nå diskutere hvordan du bruker @InjectMocks kommentar - for å injisere mock-felt i det testede objektet automatisk.
I det følgende eksemplet - bruker vi @InjectMocks å injisere spottet wordMap inn i det MyDictionarydic:
@Mock Map wordMap; @InjectMocks MyDictionary dic = ny MyDictionary (); @Test offentlig ugyldig nårUseInjectMocksAnnotation_thenCorrect () {Mockito.when (wordMap.get ("aWord")). ThenReturn ("aMeaning"); assertEquals ("aMeaning", dic.getMeaning ("aWord")); }
Og her er klassen MyDictionary:
offentlig klasse MyDictionary {Map wordMap; offentlig MyDictionary () {wordMap = ny HashMap (); } public void add (final String word, final String meaning) {wordMap.put (word, meaning); } public String getMeaning (final String word) {return wordMap.get (word); }}
7. Injisere en Mock i en spion
I likhet med testen ovenfor kan det være lurt å injisere en mock i en spion:
@Mock Map wordMap; @Spy MyDictionary spyDic = ny MyDictionary ();
Imidlertid støtter Mockito ikke å injisere mocks i spioner, og følgende testresultater med unntak:
@Test offentlig ugyldig nårUseInjectMocksAnnotation_thenCorrect () {Mockito.when (wordMap.get ("aWord")). ThenReturn ("aMeaning"); assertEquals ("aMeaning", spyDic.getMeaning ("aWord")); }
Hvis vi vil bruke en mock med en spion, kan vi manuelt injisere mocken gjennom en konstruktør:
MyDictionary (Map wordMap) {this.wordMap = wordMap; }
I stedet for å bruke kommentaren, kan vi nå opprette spionen manuelt:
@Mock Map wordMap; MyDictionary spyDic; @Før offentlig ugyldig init () {MockitoAnnotations.initMocks (dette); spyDic = Mockito.spy (ny MyDictionary (wordMap)); }
Testen vil nå bestå.
8. Kjører inn i NPE mens du bruker merknader
Ofte kan vi støte på NullPointerException når vi prøver å faktisk bruke forekomsten merket med @Håne eller @Spion:
offentlig klasse MockitoAnnotationsUninitializedUnitTest {@Mock List mockedList; @Test (forventet = NullPointerException.class) offentlig ugyldig nårMockitoAnnotationsUnitialized_thenNPEThrown () {Mockito.when (mockedList.size ()). ThenReturn (1); }}
Mesteparten av tiden skjer dette ganske enkelt fordi vi har glemt å aktivere Mockito-merknader riktig.
Så vi må huske på at hver gang vi vil bruke Mockito-merknader, må vi ta et ekstra skritt og initialisere dem som vi allerede forklarte tidligere.
9. Merknader
Endelig - her er noen notater om Mockito-merknader:
- Mockitos annoteringer minimerer repeterende opprettelseskode
- De gjør tester mer lesbare
- @InjectMocks er nødvendig for å injisere begge deler @Spion og @Håne tilfeller
10. Konklusjon
I denne raske opplæringen viste vi det grunnleggende om merknader i Mockito-biblioteket.
Implementeringen av alle disse eksemplene finner du på GitHub. Dette er et Maven-prosjekt, så det skal være enkelt å importere og kjøre som det er.
Og selvfølgelig, for mer Mockito godhet, ta en titt på serien her.