Aan de slag met Mockito @Mock, @Spy, @Captor en @InjectMocks

1. Overzicht

In deze tutorial behandelen we de annotaties van de Mockito-bibliotheek@Bespotten, @Spion, @Captor, en @InjectMocks.

Bekijk de serie hier voor meer Mockito-goedheid.

2. Schakel Mockito-annotaties in

Laten we, voordat we verder gaan, verschillende manieren onderzoeken om het gebruik van annotaties met Mockito-tests mogelijk te maken.

2.1. MockitoJUnitRunner

De eerste optie die we hebben is om annoteer de JUnit-test met een MockitoJUnitRunner zoals in het volgende voorbeeld:

@RunWith (MockitoJUnitRunner.class) openbare klasse MockitoAnnotationTest {...}

2.2. MockitoAnnotations.initMocks ()

Als alternatief kunnen we schakel Mockito-annotaties programmatisch in ook door een beroep te doen op MockitoAnnotations.initMocks ():

@Before public void init () {MockitoAnnotations.initMocks (dit); }

2.3. MockitoJUnit.rule ()

Ten slotte, we kunnen een MockitoJUnit.rule ()zoals hieronder weergegeven:

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

In dit geval moeten we eraan denken onze regel te maken openbaar.

3. @Bespotten Annotatie

De meest gebruikte annotatie in Mockito is @Bespotten. We kunnen gebruiken @Bespotten om bespotte instanties te maken en te injecteren zonder te hoeven bellen Mockito, bespotten handmatig.

In het volgende voorbeeld maken we een bespotten ArrayList met de handmatige manier zonder te gebruiken @Bespotten annotatie:

@Test openbare leegte whenNotUseMockAnnotation_thenCorrect () {List mockList = Mockito.mock (ArrayList.class); mockList.add ("een"); Mockito.verify (mockList) .add ("één"); assertEquals (0, mockList.size ()); Mockito.when (mockList.size ()). ThenReturn (100); assertEquals (100, mockList.size ()); }

En nu doen we hetzelfde, maar we injecteren de mock met de @Bespotten annotatie:

@Mock List mockedList; @Test openbare leegte whenUseMockAnnotation_thenMockIsInjected () {mockedList.add ("een"); Mockito.verify (mockedList) .add ("één"); assertEquals (0, mockedList.size ()); Mockito.when (mockedList.size ()). ThenReturn (100); assertEquals (100, mockedList.size ()); }

Merk op hoe - in beide voorbeelden, we interactie hebben met de mock en sommige van deze interacties verifiëren - alleen om er zeker van te zijn dat de mock zich correct gedraagt.

4. @Spion Annotatie

Laten we nu eens kijken hoe we het kunnen gebruiken @Spion annotatie om een ​​bestaande instantie te bespioneren.

In het volgende voorbeeld maken we een spion van een Lijst met de oude manier zonder te gebruiken @Spion annotatie:

@Test openbare leegte whenNotUseSpyAnnotation_thenCorrect () {List spyList = Mockito.spy (nieuwe ArrayList ()); spyList.add ("een"); spyList.add ("twee"); Mockito.verify (spyList) .add ("één"); Mockito.verify (spyList) .add ("twee"); assertEquals (2, spyList.size ()); Mockito.doReturn (100) .when (spyList) .size (); assertEquals (100, spyList.size ()); }

Laten we nu hetzelfde doen - de lijst bespioneren - maar doe dit met de @Spion annotatie:

@Spy List spiedList = nieuwe ArrayList (); @Test openbare leegte whenUseSpyAnnotation_thenSpyIsInjectedCorrectly () {spiedList.add ("één"); spiedList.add ("twee"); Mockito.verify (spiedList) .add ("één"); Mockito.verify (spiedList) .add ("twee"); assertEquals (2, spiedList.size ()); Mockito.doReturn (100) .when (spiedList) .size (); assertEquals (100, spiedList.size ()); }

Merk op hoe we, zoals eerder, met de spion omgaan om ervoor te zorgen dat deze zich correct gedraagt. In dit voorbeeld:

  • Gebruikte de echt methode spiedList.add () om elementen toe te voegen aan het spiedList.
  • Afgestopt de methode spiedList.size () terugbrengen 100 in plaats van 2 gebruik makend van Mockito.doReturn ().

5. @Captor Annotatie

Vervolgens - laten we eens kijken hoe we het @Captor annotatie om een ArgumentCaptor voorbeeld.

In het volgende voorbeeld maken we een ArgumentCaptor met de oude manier zonder te gebruiken @Captor annotatie:

@Test openbare leegte whenNotUseCaptorAnnotation_thenCorrect () {List mockList = Mockito.mock (List.class); ArgumentCaptor arg = ArgumentCaptor.forClass (String.class); mockList.add ("een"); Mockito.verify (mockList) .add (arg.capture ()); assertEquals ("één", arg.getValue ()); }

Laten we nu gebruikmaken van @Captorvoor hetzelfde doel - om een ArgumentCaptor voorbeeld:

@Mock List mockedList; @Captor ArgumentCaptor argCaptor; @Test openbare leegte whenUseCaptorAnnotation_thenTheSam () {mockedList.add ("een"); Mockito.verify (mockedList) .add (argCaptor.capture ()); assertEquals ("één", argCaptor.getValue ()); }

Merk op hoe de test eenvoudiger en leesbaarder wordt als we de configuratielogica verwijderen.

6. @InjectMocks Annotatie

Nu - laten we bespreken hoe u dit kunt gebruiken @InjectMocks annotatie - om automatisch nepvelden in het geteste object te injecteren.

In het volgende voorbeeld gebruiken we @InjectMocks om de mock te injecteren wordMap in de Mijn woordenboekdic:

@Mock Map wordMap; @InjectMocks MyDictionary dic = nieuwe MyDictionary (); @Test openbare leegte whenUseInjectMocksAnnotation_thenCorrect () {Mockito.when (wordMap.get ("aWord")). ThenReturn ("aMeaning"); assertEquals ("aMeaning", dic.getMeaning ("aWord")); }

En hier is de klas Mijn woordenboek:

openbare klasse MyDictionary {Map wordMap; openbare MyDictionary () {wordMap = nieuwe HashMap (); } public void add (laatste String-woord, laatste String-betekenis) {wordMap.put (woord, betekenis); } public String getMeaning (laatste String-woord) {return wordMap.get (woord); }} 

7. Een schijn in een spion injecteren

Net als bij de bovenstaande test, willen we misschien een mock in een spion injecteren:

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

Mockito ondersteunt echter niet het injecteren van spot in spionnen, en de volgende testresultaten in een uitzondering:

@Test openbare leegte whenUseInjectMocksAnnotation_thenCorrect () {Mockito.when (wordMap.get ("aWord")). ThenReturn ("aMeaning"); assertEquals ("aMeaning", spyDic.getMeaning ("aWord")); }

Als we een mock met een spion willen gebruiken, kunnen we de mock handmatig injecteren via een constructor:

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

In plaats van de annotatie te gebruiken, kunnen we de spion nu handmatig maken:

@Mock Map wordMap; MyDictionary spyDic; @Before public void init () {MockitoAnnotations.initMocks (dit); spyDic = Mockito.spy (nieuwe MyDictionary (wordMap)); } 

De test zal nu slagen.

8. NPE tegenkomen tijdens het gebruik van annotatie

Vaak doen we dat tegenkomen NullPointerException wanneer we proberen de instantie te gebruiken die is geannoteerd met @Bespotten of @Spion:

openbare klasse MockitoAnnotationsUninitializedUnitTest {@Mock List mockedList; @Test (verwacht = NullPointerException.class) openbare leegte whenMockitoAnnotationsUninitialized_thenNPEThrown () {Mockito.when (mockedList.size ()). ThenReturn (1); }}

Meestal gebeurt dit simpelweg omdat we zijn vergeten Mockito-annotaties correct in te schakelen.

We moeten dus in gedachten houden dat elke keer dat we Mockito-annotaties willen gebruiken, we een extra stap moeten nemen en ze moeten initialiseren zoals we eerder al hebben uitgelegd.

9. Opmerkingen

Eindelijk - hier zijn enkele opmerkingen over Mockito-annotaties:

  • De annotaties van Mockito minimaliseren de herhaalde code voor het maken van nepcreatie
  • Ze maken tests beter leesbaar
  • @InjectMocks is nodig om beide te injecteren @Spion en @Bespotten gevallen

10. Conclusie

In deze korte tutorial hebben we de basisprincipes van annotaties in de Mockito-bibliotheek.

De implementatie van al deze voorbeelden is te vinden op GitHub. Dit is een Maven-project, dus het moet gemakkelijk te importeren en uit te voeren zijn zoals het is.

En natuurlijk, voor meer Mockito-goedheid, bekijk de serie hier.