Kom godt i gang med Mockito @Mock, @Spy, @Captor og @InjectMocks

1. Oversigt

I denne vejledning dækker vi annoteringer af Mockito-biblioteket@Mock, @Spion, @Captorog @InjectMocks.

For mere Mockito godhed, se på serien her.

2. Aktivér Mockito-kommentarer

Før vi går videre, lad os undersøge forskellige måder at muliggøre brugen af ​​kommentarer med Mockito-tests.

2.1. MockitoJUnitRunner

Den første mulighed, vi har, er at 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-annoteringer programmatisk også ved at påberåbe sig MockitoAnnotations.initMocks ():

@Før offentlig ugyldig init () {MockitoAnnotations.initMocks (dette); }

2.3. MockitoJUnit.rule ()

Endelig vi kan bruge en MockitoJUnit.rule ()som vist nedenfor:

offentlig klasse MockitoInitWithMockitoJUnitRuleUnitTest {@Rule public MockitoRule initRule = MockitoJUnit.rule (); ...}

I dette tilfælde skal vi huske at gøre vores regel offentlig.

3. @Mock Kommentar

Den mest anvendte annotering i Mockito er @Mock. Vi kan bruge @Mock at oprette og injicere spottede forekomster uden at skulle ringe Mockito.mock manuelt.

I det følgende eksempel opretter vi en mocked ArrayList med den manuelle måde uden brug @Mock kommentar:

@Test offentlig ugyldig nårNotUseMockAnnotation_thenCorrect () {List mockList = Mockito.mock (ArrayList.class); mockList.add ("en"); Mockito.verify (mockList) .add ("en"); assertEquals (0, mockList.size ()); Mockito.when (mockList.size ()). Derefter Retur (100); assertEquals (100, mockList.size ()); }

Og nu gør vi det samme, men vi injicerer mock ved hjælp af @Mock kommentar:

@Mock List mockedList; @Test offentlig ugyldigt nårUseMockAnnotation_thenMockIsInjected () {mockedList.add ("one"); Mockito.verify (mockedList) .add ("one"); assertEquals (0, mockedList.size ()); Mockito.when (mockedList.size ()). Derefter Retur (100); assertEquals (100, mockedList.size ()); }

Bemærk hvordan - i begge eksempler interagerer vi med mocken og verificerer nogle af disse interaktioner - bare for at sikre, at mocken opfører sig korrekt.

4. @Spion Kommentar

Lad os nu se, hvordan du bruger @Spion kommentar for at spionere på en eksisterende forekomst.

I det følgende eksempel opretter vi en spion af en Liste med den gamle måde uden brug @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). Når (spyList) .størrelse (); assertEquals (100, spyList.size ()); }

Lad os nu gøre det samme - spionér på listen - men gør det ved hjælp af @Spion kommentar:

@Spy-liste spiedList = ny ArrayList (); @Test offentlig ugyldigt nårUseSpyAnnotation_thenSpyIsInjectedCorrectly () {spiedList.add ("one"); spiedList.add ("to"); Mockito.verify (spiedList) .add ("en"); Mockito.verify (spiedList) .add ("to"); assertEquals (2, spiedList.size ()); Mockito.doReturn (100). Når (spiedList) .størrelse (); assertEquals (100, spiedList.size ()); }

Bemærk hvordan du som før interagerer med spionen her for at sikre, at den opfører sig korrekt. I dette eksempel:

  • Brugt ægte metode spiedList.add () for at tilføje elementer til spiedList.
  • Stubbed metoden spiedList.size () at vende tilbage 100 i stedet for 2 ved brug af Mockito.doReturn ().

5. @Captor Kommentar

Næste - lad os se, hvordan du bruger @Captor kommentar for at oprette en ArgumentCaptor eksempel.

I det følgende eksempel - opretter vi en ArgumentCaptor med den gamle måde uden brug @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 ("en", arg.getValue ()); }

Lad os nu gøre brug af @Captormed det samme formål - at skabe en ArgumentCaptor eksempel:

@Mock List mockedList; @Captor ArgumentCaptor argCaptor; @Test offentlig ugyldig nårUseCaptorAnnotation_thenTheSam () {mockedList.add ("one"); Mockito.verify (mockedList) .add (argCaptor.capture ()); assertEquals ("en", argCaptor.getValue ()); }

Bemærk, hvordan testen bliver enklere og mere læselig, når vi tager konfigurationslogikken ud.

6. @InjectMocks Kommentar

Lad os nu diskutere, hvordan man bruger @InjectMocks kommentar - for automatisk at indsprøjte mock-felter i det testede objekt.

I det følgende eksempel bruger vi @InjectMocks at injicere mock wordMap ind i MyDictionarydic:

@Mock Map wordMap; @InjectMocks MyDictionary dic = ny MyDictionary (); @Test offentligt ugyldigt nårUseInjectMocksAnnotation_thenCorrect () {Mockito.when (wordMap.get ("aWord")). DerefterReturn ("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. Injektion af en mock i en spion

I lighed med ovenstående test vil vi måske injicere en mock i en spion:

@Mock Map wordMap; @Spy MyDictionary spyDic = ny MyDictionary ();

Imidlertid understøtter Mockito ikke indsprøjtning af mocks i spioner, og følgende testresultater med en undtagelse:

@Test offentligt ugyldigt nårUseInjectMocksAnnotation_thenCorrect () {Mockito.when (wordMap.get ("aWord")). DerefterReturn ("aMeaning"); assertEquals ("aMeaning", spyDic.getMeaning ("aWord")); }

Hvis vi vil bruge en mock med en spion, kan vi manuelt injicere mocken gennem en konstruktør:

MyDictionary (Map wordMap) {this.wordMap = wordMap; }

I stedet for at bruge kommentaren kan vi nu oprette spionen manuelt:

@Mock Map wordMap; MyDictionary spyDic; @Før offentlig ugyldig init () {MockitoAnnotations.initMocks (dette); spyDic = Mockito.spy (ny MyDictionary (wordMap)); } 

Testen vil nu bestå.

8. Kører ind i NPE, mens du bruger kommentar

Ofte kan vi løbe ind i NullPointerException når vi forsøger at bruge den instans, der er kommenteret med @Mock eller @Spion:

offentlig klasse MockitoAnnotationsUninitializedUnitTest {@Mock List mockedList; @Test (forventet = NullPointerException.class) offentlig ugyldigt nårMockitoAnnotationsUninitialized_thenNPEThrown () {Mockito.when (mockedList.size ()). ThenReturn (1); }}

For det meste sker dette simpelthen fordi vi glemte at aktivere Mockito-kommentarer korrekt.

Så vi skal huske på, at hver gang vi vil bruge Mockito-kommentarer, skal vi tage et ekstra trin og initialisere dem som vi allerede har forklaret tidligere.

9. Bemærkninger

Endelig - her er nogle noter om Mockito-kommentarer:

  • Mockitos annoteringer minimerer gentagne koder til oprettelse af mock
  • De gør test mere læsbare
  • @InjectMocks er nødvendig til injektion af begge dele @Spion og @Mock tilfælde

10. Konklusion

I denne hurtige vejledning viste vi det grundlæggende i bemærkninger i Mockito-biblioteket.

Implementeringen af ​​alle disse eksempler kan findes på GitHub. Dette er et Maven-projekt, så det skal være let at importere og køre som det er.

Og selvfølgelig, for mere Mockito godhed, se på serien her.