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.