Erste Schritte mit Mockito @Mock, @Spy, @Captor und @InjectMocks

1. Übersicht

In diesem Tutorial werden die Anmerkungen der Mockito-Bibliothek behandelt - @Mock , @Spy , @Captor und @InjectMocks .

Weitere Informationen zu Mockito finden Sie in der Serie hier.

2. Aktivieren Sie Mockito Annotations

Bevor wir fortfahren, wollen wir verschiedene Möglichkeiten untersuchen, um die Verwendung von Anmerkungen mit Mockito-Tests zu ermöglichen.

2.1. MockitoJUnitRunner

Die erste Möglichkeit besteht darin, den JUnit-Test mit einem MockitoJUnitRunner wie im folgenden Beispiel zu kommentieren :

@RunWith(MockitoJUnitRunner.class) public class MockitoAnnotationTest { ... }

2.2. MockitoAnnotations.initMocks ()

Alternativ können wir Mockito-Annotationen auch programmgesteuert aktivieren , indem wir MockitoAnnotations.initMocks () aufrufen :

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

2.3. MockitoJUnit.rule ()

Zuletzt können wir eine MockitoJUnit.rule () wie unten gezeigt verwenden:

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

In diesem Fall müssen wir daran denken, unsere Regel öffentlich zu machen .

3. @Mock Annotation

Die am häufigsten verwendete Anmerkung in Mockito ist @Mock . Wir können @Mock verwenden , um verspottete Instanzen zu erstellen und einzufügen , ohne Mockito.mock manuell aufrufen zu müssen.

Im folgenden Beispiel erstellen wir eine verspottete ArrayList auf manuelle Weise ohne Verwendung der @ Mock- Annotation:

@Test public void whenNotUseMockAnnotation_thenCorrect() { List mockList = Mockito.mock(ArrayList.class); mockList.add("one"); Mockito.verify(mockList).add("one"); assertEquals(0, mockList.size()); Mockito.when(mockList.size()).thenReturn(100); assertEquals(100, mockList.size()); }

Und jetzt machen wir dasselbe, aber wir injizieren den Mock mit der Annotation @Mock :

@Mock List mockedList; @Test public void whenUseMockAnnotation_thenMockIsInjected() { mockedList.add("one"); Mockito.verify(mockedList).add("one"); assertEquals(0, mockedList.size()); Mockito.when(mockedList.size()).thenReturn(100); assertEquals(100, mockedList.size()); }

Beachten Sie, wie wir in beiden Beispielen mit dem Modell interagieren und einige dieser Interaktionen überprüfen, um sicherzustellen, dass sich das Modell korrekt verhält.

4. @Spy Annotation

Lassen Sie uns nun sehen, wie Sie mit der @Spy- Annotation eine vorhandene Instanz ausspionieren.

Im folgenden Beispiel erstellen wir einen Spion einer Liste auf die alte Art und Weise, ohne die @ Spy- Annotation zu verwenden:

@Test public void whenNotUseSpyAnnotation_thenCorrect() { List spyList = Mockito.spy(new ArrayList()); spyList.add("one"); spyList.add("two"); Mockito.verify(spyList).add("one"); Mockito.verify(spyList).add("two"); assertEquals(2, spyList.size()); Mockito.doReturn(100).when(spyList).size(); assertEquals(100, spyList.size()); }

Machen wir jetzt dasselbe - spionieren Sie die Liste aus - aber verwenden Sie dazu die Annotation @Spy :

@Spy List spiedList = new ArrayList(); @Test public void whenUseSpyAnnotation_thenSpyIsInjectedCorrectly() { spiedList.add("one"); spiedList.add("two"); Mockito.verify(spiedList).add("one"); Mockito.verify(spiedList).add("two"); assertEquals(2, spiedList.size()); Mockito.doReturn(100).when(spiedList).size(); assertEquals(100, spiedList.size()); }

Beachten Sie, wie wir nach wie vor mit dem Spion interagieren, um sicherzustellen, dass er sich korrekt verhält. In diesem Beispiel haben wir:

  • Verwendete die reale Methode spiedList.add () , um der spiedList Elemente hinzuzufügen .
  • Stubbte die Methode spiedList.size () , um mit Mockito.doReturn () 100 statt 2 zurückzugeben .

5. @ Captor Annotation

Weiter - sehen wir uns an, wie Sie mit der Annotation @Captor eine ArgumentCaptor- Instanz erstellen .

Im folgenden Beispiel erstellen wir einen ArgumentCaptor auf die alte Weise, ohne die Annotation @Captor zu verwenden :

@Test public void whenNotUseCaptorAnnotation_thenCorrect() { List mockList = Mockito.mock(List.class); ArgumentCaptor arg = ArgumentCaptor.forClass(String.class); mockList.add("one"); Mockito.verify(mockList).add(arg.capture()); assertEquals("one", arg.getValue()); }

Verwenden wir jetzt @Captor für denselben Zweck - um eine ArgumentCaptor- Instanz zu erstellen :

@Mock List mockedList; @Captor ArgumentCaptor argCaptor; @Test public void whenUseCaptorAnnotation_thenTheSam() { mockedList.add("one"); Mockito.verify(mockedList).add(argCaptor.capture()); assertEquals("one", argCaptor.getValue()); }

Beachten Sie, wie der Test einfacher und lesbarer wird, wenn wir die Konfigurationslogik herausnehmen.

6. @InjectMocks Annotation

Lassen Sie uns nun diskutieren, wie die Annotation @InjectMocks verwendet wird , um Scheinfelder automatisch in das getestete Objekt einzufügen .

Im folgenden Beispiel - wir verwenden @InjectMocks die mock zu injizieren wordMap in die MyDictionary dic :

@Mock Map wordMap; @InjectMocks MyDictionary dic = new MyDictionary(); @Test public void whenUseInjectMocksAnnotation_thenCorrect() { Mockito.when(wordMap.get("aWord")).thenReturn("aMeaning"); assertEquals("aMeaning", dic.getMeaning("aWord")); }

Und hier ist die Klasse MyDictionary :

public class MyDictionary { Map wordMap; public MyDictionary() { wordMap = new 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. Einen Spion in einen Spion injizieren

Ähnlich wie beim obigen Test möchten wir vielleicht einem Spion einen Schein injizieren:

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

Mockito unterstützt jedoch nicht das Injizieren von Spott in Spione, und die folgenden Testergebnisse führen zu einer Ausnahme:

@Test public void whenUseInjectMocksAnnotation_thenCorrect() { Mockito.when(wordMap.get("aWord")).thenReturn("aMeaning"); assertEquals("aMeaning", spyDic.getMeaning("aWord")); }

Wenn wir einen Mock mit einem Spion verwenden möchten, können wir den Mock manuell durch einen Konstruktor injizieren:

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

Anstatt die Anmerkung zu verwenden, können wir den Spion jetzt manuell erstellen:

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

Der Test wird nun bestanden.

8. Während der Verwendung von Annotation auf NPE stoßen

Oft können wir den Weg laufen Nullpointer , wenn wir versuchen , um tatsächlich die Instanz mit kommentierten verwenden @Mock oder @Spy :

public class MockitoAnnotationsUninitializedUnitTest { @Mock List mockedList; @Test(expected = NullPointerException.class) public void whenMockitoAnnotationsUninitialized_thenNPEThrown() { Mockito.when(mockedList.size()).thenReturn(1); } }

Meistens geschieht dies einfach, weil wir vergessen haben, Mockito-Anmerkungen ordnungsgemäß zu aktivieren.

Wir müssen also berücksichtigen, dass wir jedes Mal, wenn wir Mockito-Anmerkungen verwenden möchten, einen zusätzlichen Schritt unternehmen und sie initialisieren müssen, wie wir bereits zuvor erläutert haben.

9. Notizen

Zum Schluss noch ein paar Anmerkungen zu Mockito-Anmerkungen:

  • Mockitos Anmerkungen minimieren sich wiederholenden Code für die Erstellung von Mocks
  • Sie machen Tests lesbarer
  • @InjectMocks ist notwendig , dass beide Injektion @Spy und @Mock Instanzen

10. Schlussfolgerung

In diesem kurzen Tutorial haben wir die Grundlagen von Anmerkungen in der Mockito-Bibliothek gezeigt .

Die Implementierung all dieser Beispiele finden Sie auf GitHub. Dies ist ein Maven-Projekt, daher sollte es einfach zu importieren und auszuführen sein.

Und natürlich, um mehr Mockito-Güte zu erfahren, schauen Sie sich die Serie hier an.