different types matchers provided mockito
Wie schreibe ich Testfälle für den Anmeldebildschirm?
Eine Einführung in verschiedene Arten von Matchern in Mockito.
Verspottungen und Spione in Mockito wurden in unserem vorherigen Tutorial ausführlich erklärt Mockito Trainingsreihe .
Was sind Matcher?
Matcher sind wie Regex oder Platzhalter, bei denen Sie anstelle einer bestimmten Eingabe (und / oder Ausgabe) einen Bereich / Typ der Eingabe / Ausgabe angeben, auf dessen Grundlage Stubs / Spione ruhen und Aufrufe von Stubs überprüft werden können.
Alle Mockito-Matcher sind Teil von Mockito ’ statische Klasse.
Matcher sind ein leistungsstarkes Tool, das eine Kurzform zum Einrichten von Stubs sowie zum Überprüfen von Aufrufen auf den Stubs ermöglicht, indem Argumenteingaben als generische Typen für bestimmte Werte je nach Anwendungsfall oder Szenario erwähnt werden.
Was du lernen wirst:
Arten von Matchern in Mockito
In Mockito gibt es im Allgemeinen zwei Arten von Matchern oder in Bezug auf die Verwendung können Matcher für die folgenden 2 Kategorien verwendet werden:
- Argument Matchers während des Stub-Setups
- Verifizierungs-Matcher zum Überprüfen der tatsächlichen Aufrufe von Stubs
Für beide Arten von Matchern, d. H. Argument und Verifikation, bietet Mockito eine große Anzahl von Matchern (Klicken Hier um eine vollständige Liste der Matcher zu erhalten).
Argument Matchers
Nachfolgend sind die am häufigsten verwendeten aufgeführt:
Lassen Sie uns für alle folgenden Punkte eine IntegerList testen:
final List mockedIntList = mock(ArrayList.class);
# 1) any () - Akzeptiert jedes Objekt (einschließlich null).
when (mockedIntList.get( any ())).thenReturn(3);
#zwei) any (Java-Sprachkurs) -
Beispiel : any (ClassUnderTest.class) - Dies ist eine spezifischere Variante von any () und akzeptiert nur Objekte des Klassentyps, der als Vorlagenparameter angegeben ist.
when (mockedIntList.get( any (Integer.class))).thenReturn(3);
#3) anyBoolean (), anyByte (), anyInt (), anyString (), anyDouble (), anyFloat (), anyList () und viele mehr - Alle diese akzeptieren alle Objekte des entsprechenden Datentyps sowie Nullwerte.
when (mockedIntList.get( any Int())).thenReturn(3);
# 4) Spezifische Argumente - In Fällen, in denen tatsächliche Argumente im Voraus bekannt sind, wird immer empfohlen, sie zu verwenden, da sie mehr Vertrauen gegenüber generischen Argumenttypen bieten.
Beispiel:
when(mockedIntList.get(1)).thenReturn(3);
Verifizierungs-Matcher
Es gibt einige spezialisierte Matcher, die verfügbar sind, um Dinge wie Nein zu erwarten / zu behaupten. von Anrufungen auf dem Schein.
Betrachten wir für alle unten aufgeführten Matcher dieselbe Liste von Beispielen, die wir zuvor verwendet haben.
final List mockedIntList = mock(ArrayList.class);
# 1) Scheinaufrufe
(ich) Durch einfaches Aufrufen von Mock wird überprüft, ob die verspottete Methode aufgerufen / interagiert wurde oder nicht, indem die Größe der verspotteten Liste auf 5 festgelegt wird.
//arrange when(mockedList.size()).thenReturn(5); // act int size = mockedList.size(); // assert verify(mockedList).size();
(ii) Die spezifische Anzahl von Interaktionen mit einer verspotteten Methode überprüft die Anzahl von Nr. von Zeiten wurde erwartet, dass der Schein aufgerufen wurde.
//arrange when(mockedList.size()).thenReturn(5); // act int size = mockedList.size(); // assert verify(mockedList, times(1)).size();
Um 0 Interaktionen zu überprüfen, ändern Sie einfach den Wert von 1 auf 0 als Argument für times () matcher.
//arrange when(mockedList.size()).thenReturn(5); // act int size = mockedList.size(); // assert verify(mockedList, times(0)).size();
Bei Fehlern werden die folgenden Ausnahmen zurückgegeben:
zu) Wenn die erwarteten Aufrufe geringer sind als die tatsächlichen Aufrufe:
Beispiel: 2 Mal gesucht, aber 3 Mal aufgerufen, dann kehrt Mockito zurück - “ verification.TooManyActualInvocations ''
Beispielcode:
final List mockedIntList = mock(ArrayList.class); // Arrange when(mockedIntList.get(anyInt())).thenReturn(3); // Act int response = mockedIntList.get(5); response = mockedIntList.get(3); response = mockedIntList.get(100); // Assert verify(mockedIntList, times(2)).get(anyInt());
b) Wenn die erwarteten Aufrufe größer sind als die tatsächlichen Aufrufe:
Beispiel: 2 Mal gesucht, aber 1 Mal aufgerufen, dann kehrt Mockito zurück - “ verification.TooLittleActualInvocations ''
final List mockedIntList = mock(ArrayList.class); // Arrange when(mockedIntList.get(anyInt())).thenReturn(3); // Act int response = mockedIntList.get(5); response = mockedIntList.get(3); response = mockedIntList.get(100); // Assert verify(mockedIntList, times(4)).get(anyInt());
(iii) Keine Interaktionen mit der spezifischen Methode des verspotteten Objekts.
final List mockedIntList = mock(ArrayList.class); // Arrange when(mockedIntList.get(anyInt())).thenReturn(3); // Act int response = mockedIntList.get(5); // Assert verify(mockedIntList, never()).size();
(iv) Überprüfen der Reihenfolge verspotteter Interaktionen - Dies ist besonders nützlich, wenn Sie die Reihenfolge sicherstellen möchten, in der die Methoden für die verspotteten Objekte aufgerufen wurden.
Beispiel: Datenbankähnliche Vorgänge, bei denen ein Test die Reihenfolge überprüfen sollte, in der die Datenbankaktualisierungen durchgeführt wurden.
Um dies anhand eines Beispiels zu veranschaulichen - Fahren wir mit derselben Beispielliste fort.
Nehmen wir nun an, dass die Reihenfolge der Aufrufe von Listenmethoden der Reihe nach war, d. H. Get (5), size (), get (2). Daher sollte auch die Reihenfolge der Überprüfung dieselbe sein.
// Arrange when(mockedIntList.get(anyInt())).thenReturn(3); when(mockedIntList.size()).thenReturn(100); InOrder mockInvocationSequence = Mockito.inOrder(mockedIntList); // Act int response = mockedIntList.get(5); int size = mockedIntList.size(); response = mockedIntList.get(2); // Assert mockInvocationSequence.verify(mockedIntList, times(1)).get(anyInt()); mockInvocationSequence.verify(mockedIntList).size(); mockInvocationSequence.verify(mockedIntList, times(1)).get(anyInt());
Im Falle einer falschen Überprüfungssequenz wird von Mockito eine Ausnahme ausgelöst - d. H. verification.VerificationInOrderFailure ”.
wie man zwei Dateien unter Linux vergleicht
Wenn ich im obigen Beispiel die Reihenfolge der Überprüfung durch Vertauschen der letzten beiden Zeilen ändere, wird die Ausnahme 'VerificationInOrderFailure' angezeigt.
// Arrange when(mockedIntList.get(anyInt())).thenReturn(3); when(mockedIntList.size()).thenReturn(100); InOrder mockInvocationSequence = Mockito.inOrder(mockedIntList); // Act int response = mockedIntList.get(5); int size = mockedIntList.size(); response = mockedIntList.get(2); // Assert mockInvocationSequence.verify(mockedIntList, times(1)).get(anyInt()); mockInvocationSequence.verify(mockedIntList, times(1)).get(anyInt()); mockInvocationSequence.verify(mockedIntList).size();
(v) Stellen Sie sicher, dass die Interaktion mindestens / höchstens mehrmals aufgetreten ist.
(zu) mindestens:
Beispiel: atleast (3) - Überprüft, ob das verspottete Objekt während des Tests mindestens dreimal aufgerufen / mit mindestens interagiert wurde. Daher sollte jede der Interaktionen 3 oder größer als 3 die Überprüfung erfolgreich machen.
// Arrange when(mockedIntList.get(anyInt())).thenReturn(3); // Act int response = mockedIntList.get(5); response = mockedIntList.get(2); // Assert verify(mockedIntList, atLeast(2)).get(anyInt());
Im Falle von Fehlern, d. H. Wenn die tatsächlichen Aufrufe nicht übereinstimmen, wird dieselbe Ausnahme ausgelöst wie beim times () -Matcher, d. H. verification.TooLittleActualInvocations ”
(b) höchstens:
Beispiel: atmost (3) - Überprüft, ob das verspottete Objekt während des Tests mindestens dreimal aufgerufen / interagiert wurde. Jede der 0,1,2 oder 3 Interaktionen mit dem Mock sollte die Verifizierung erfolgreich machen.
// Arrange when(mockedIntList.get(anyInt())).thenReturn(3); // Act int response = mockedIntList.get(5); response = mockedIntList.get(2); // Assert verify(mockedIntList, atMost(2)).get(anyInt()); verify(mockedIntList, atMost(2)).size();
# 2) Argumentabgleich
Im obigen Aufruf können Matcher mit den Argument-Matchern kombiniert werden, um die Argumente zu validieren, mit denen der Mock aufgerufen wurde.
- irgendein()
- Spezifische Werte - Überprüfen Sie anhand der spezifischen Werte, ob die Argumente vorher bekannt sind.
- Andere Argument-Matcher wie - anyInt (), anyString () usw.
Tipps
# 1) Verwenden der Argumenterfassung während der Überprüfung
Die Überprüfung der Argumenterfassung ist normalerweise nützlich, wenn das von einer gestoppelten Methode verwendete Argument nicht direkt über einen Methodenaufruf übergeben wird, sondern intern erstellt wird, wenn die zu testende Methode aufgerufen wird.
Dies ist im Wesentlichen nützlich, wenn Ihre Methode von einem oder mehreren Mitarbeitern abhängt, deren Verhalten gestoppt wurde. Die an diese Mitarbeiter übergebenen Argumente sind ein internes Objekt oder ein völlig neuer Argumentationssatz.
Die Überprüfung des tatsächlichen Arguments, mit dem die Mitarbeiter aufgerufen worden wären, gewährleistet viel Vertrauen in den zu testenden Code.
Mockito stellt ArgumentCaptor zur Verfügung, das zur Überprüfung verwendet werden kann. Wenn dann 'AgumentCaptor.getValue ()' aufgerufen wird, können wir das tatsächlich erfasste Argument gegen das erwartete geltend machen.
Um dies zu veranschaulichen, beziehen Sie sich auf das folgende Beispiel:
In der folgenden Methode ist berechnePreis das Modell mit der Klasse InventoryModel, die innerhalb des Methodenkörpers erstellt wird und dann von InventoryService zur Aktualisierung verwendet wird.
Wenn Sie nun einen Test schreiben möchten, um zu überprüfen, mit welchem Argument der Inventarservice aufgerufen wurde, können Sie einfach das ArgumentCaptor-Objekt vom Typ InventoryModel-Klasse verwenden.
Testmethode:
public double calculatePrice(int itemSkuCode) { double price = 0; // get Item details ItemSku sku = itemService.getItemDetails(itemSkuCode); // update item inventory InventoryModel model = new InventoryModel(); model.setItemSku(sku); model.setItemSuppliers(new String(){'Supplier1'}); inventoryService.updateInventory(model, 1); return sku.getPrice(); }
Testcode: Sehen Sie sich den Überprüfungsschritt an, in dem inventarService überprüft wird. Das argumentCaptor-Objekt wird ersetzt, für das das Argument übereinstimmen muss.
Aktivieren Sie dann einfach den Wert, indem Sie die Methode getValue () für das ArgumentCaptor-Objekt aufrufen.
Beispiel: ArgumentCaptorObject.getValue ()
public void calculatePrice_withValidItemSku_returnsSuccess() { // Arrange ItemSku item1 = new ItemSku(); item1.setApplicableDiscount(5.00); item1.setPrice(100.00); CustomerProfile customerProfile = new CustomerProfile(); customerProfile.setExtraLoyaltyDiscountPercentage(2.00); double expectedPrice = 93.00; // Arrange when(mockedItemService.getItemDetails(anyInt())).thenReturn(item1); ArgumentCaptor argCaptorInventoryModel = ArgumentCaptor.forClass(InventoryModel.class); // Act priceCalculator.calculatePrice(1234); // Assert verify(mockedItemService).getItemDetails(anyInt()); verify(mockedInventoryService).updateInventory(argCaptorInventoryModel.capture(), eq(1)); assertEquals(argCaptorInventoryModel.getValue().itemSku, item1);
Ohne ArgumentCaptor wäre es nicht möglich zu identifizieren, mit welchem Argument der Serviceabruf durchgeführt wurde. Am besten verwenden Sie 'any ()' oder 'any (InventoryModel.class)', um die Argumente zu überprüfen.
# 2) Häufige Ausnahmen / Fehler bei der Verwendung von Matchern
Bei der Verwendung von Matchern sollten bestimmte Konventionen befolgt werden. Wenn diese nicht befolgt werden, wird eine Ausnahme ausgelöst. Das häufigste, auf das ich gestoßen bin, ist das Stubben und Überprüfen.
Wenn Sie argumentMatchers verwenden und die stubbed-Methode mehr als ein Argument hat, sollten entweder alle Argumente mit Matchern erwähnt werden, andernfalls sollte keines von ihnen Matcher haben. Was bedeutet das nun?
Versuchen wir, dies anhand eines Szenarios zu verstehen (und dann ein Codebeispiel für dieses Szenario).
- Angenommen, die zu testende Methode hat eine Signatur wie -
concatenateString (String arg1, String arg2) - Angenommen, Sie kennen den Wert von arg1, aber arg2 ist unbekannt, und entscheiden sich daher für die Verwendung eines Argumentvergleichers wie - any () oder anyString () und geben einen Wert für das erste Argument wie einen Text „Hallo“ an.
- Wenn der obige Schritt implementiert und der Test ausgeführt wird, löst der Test eine Ausnahme mit dem Namen 'InvalidUseOfMatchersException' aus.
Versuchen wir dies anhand eines Beispiels zu verstehen:
Testcode:
// Arrange when(a gMatcher.concatenateString('hello', anyString())).thenReturn('hello world!'); // Act String response = argMatcher.concatenateString('hello', 'abc'); // Assert verify(argMatcher).concatenateString(anyString(), anyString());
Testklasse:
public class ArgMatcher { public String concatenateString(String arg1, String arg2) { return arg1.concat(arg2); } }
Wenn der obige Test ausgeführt wird, kehrt er in „ InvalidUseOfMatchersException ''
Was ist nun der Grund für diese Ausnahme?
Es ist das Stubbing unter Verwendung von Teil-Matchern und Teil-festen Zeichenfolgen, d. H. Wir haben einen Argument-Matcher als 'Hallo' und den zweiten als anyString () erwähnt. Jetzt gibt es zwei Möglichkeiten, um diese Art von Ausnahmen zu beseitigen (Bitte beachten Sie auch, dass dieses Verhalten sowohl für Mock-Setups als auch für das Verhalten gilt).
Interviewfragen für .net Entwickler
# 1) Verwenden Sie Argument Matchers für alle Argumente:
// Arrange when(a gMatcher.concatenateString(anyString(), anyString())).thenReturn('hello world!'); // Act String response = argMatcher.concatenateString('hello', 'abc'); // Assert verify(argMatcher).concatenateString(anyString(), anyString());
# 2) Verwenden Sie eq () als Argument Matcher, wenn das Argument bekannt ist. Anstatt das Argument als 'Hallo' anzugeben, geben Sie es als 'eq' ('Hallo') an. Dies sollte das Stubbing erfolgreich machen.
// Arrange when(argMatcher.concatenateString(anyString(), eq('world'))).thenReturn('hello world!'); // Act String response = argMatcher.concatenateString('hello', 'world'); // Assert verify(argMatcher).concatenateString(anyString(), eq('world'));
Fazit
In diesem Artikel haben wir gesehen, wie verschiedene Arten von Matchern verwendet werden, die von Mockito bereitgestellt werden.
Hier haben wir die am häufigsten verwendeten behandelt. Um auf die vollständige Liste zu verweisen, ist die Dokumentation der Mockito Library eine gute Referenzquelle.
In unserem nächsten Tutorial erfahren Sie mehr über private, statische und nichtige Verspottungsmethoden.
PREV Tutorial | NÄCHSTES Tutorial
Literatur-Empfehlungen
- Erstellen von Mocks und Spionen in Mockito mit Codebeispielen
- Mockito Tutorial: Mockito Framework zum Verspotten im Unit Testing
- Arten von Risiken in Softwareprojekten
- Python-Datentypen
- C ++ - Datentypen
- Top 12 Fragen zum Mockito-Interview (Mocking Framework-Interview)
- Verspotten privater, statischer und nichtiger Methoden mit Mockito
- Arten der Vererbung in C ++