mocking private static
Lernen Sie das Verspotten privater, statischer und nichtiger Methoden in Mockito anhand von Beispielen:
In dieser Reihe von praktischen Übungen Tutorials zu Mockito Wir haben uns das angeschaut verschiedene Arten von Mockito Matchern im letzten Tutorial.
Im Allgemeinen fallen das Verspotten privater und statischer Methoden unter die Kategorie des ungewöhnlichen Verspottens.
Wenn die Notwendigkeit besteht, private und statische Methoden / Klassen zu verspotten, weist dies auf schlecht überarbeiteten Code hin und ist kein wirklich testbarer Code. Es ist höchstwahrscheinlich, dass ein älterer Code, der nicht verwendet wurde, sehr einheitlich für Tests geeignet war.
Trotzdem gibt es immer noch Unterstützung für das Verspotten privater und statischer Methoden durch wenige Unit-Test-Frameworks wie PowerMockito (und nicht direkt von Mockito).
Das Verspotten von 'void' -Methoden ist häufig, da es möglicherweise Methoden gibt, die im Wesentlichen nichts zurückgeben, z. B. das Aktualisieren einer Datenbankzeile (betrachten Sie dies als eine PUT-Operation eines Rest-API-Endpunkts, der eine Eingabe akzeptiert und keine Ausgabe zurückgibt).
Mockito bietet volle Unterstützung für das Verspotten von Void-Methoden, die wir anhand von Beispielen in diesem Artikel sehen werden.
Beispieltestfälle für Webanwendungen
Was du lernen wirst:
- Powermock - Eine kurze Einführung
- Private Methoden verspotten
- Statische Methoden verspotten
- Voiding-Methoden verspotten
- Tipps
- Fazit
- Literatur-Empfehlungen
Powermock - Eine kurze Einführung
Für Mockito gibt es keine direkte Unterstützung für das Verspotten privater und statischer Methoden. Um private Methoden zu testen, müssen Sie Refactor den Code Um den Zugriff auf protected (oder package) zu ändern, müssen Sie statische / endgültige Methoden vermeiden.
Mockito bietet meiner Meinung nach absichtlich keine Unterstützung für diese Art von Mocks, da die Verwendung dieser Art von Codekonstrukten Codegerüche und schlecht gestalteter Code sind.
Es gibt jedoch Frameworks, die das Verspotten privater und statischer Methoden unterstützen.
Powermock erweitert die Funktionen anderer Frameworks wie EasyMock und Mockito und bietet die Möglichkeit, statische und private Methoden zu verspotten.
# 1) Wie: Powermock tut dies mit Hilfe einer benutzerdefinierten Bytecode-Manipulation, um das Verspotten privater und statischer Methoden, Endklassen, Konstruktoren usw. zu unterstützen.
# 2) Unterstützte Pakete: Powermock bietet zwei Erweiterungs-APIs - eine für Mockito und eine für easyMock. Für diesen Artikel werden wir Beispiele mit der Mockito-Erweiterung für Power Mock schreiben.
# 3) Syntax ::Powermockito hat eine fast ähnliche Syntax wie Mockito, mit Ausnahme einiger zusätzlicher Methoden zum Verspotten statischer und privater Methoden.
# 4) Powermockito Setup
Um die Mockito-Bibliothek in gradle-basierte Projekte aufzunehmen, müssen die folgenden Bibliotheken aufgenommen werden:
testCompile group: 'org.powermock', name: 'powermock-api-mockito2', version: '1.7.4' testCompile group: 'org.powermock', name: 'powermock-module-junit4', version: '1.7.4'
Ähnliche Abhängigkeiten sind auch für Maven verfügbar.
Powermock-api-mockito2 - Die Bibliothek muss Mockito-Erweiterungen für Powermockito enthalten.
Powermock-Modul-junit4 - Das Modul muss PowerMockRunner enthalten (ein benutzerdefinierter Runner, der zum Ausführen von Tests mit PowerMockito verwendet wird).
Ein wichtiger Punkt hierbei ist, dass PowerMock Junit5-Testläufer nicht unterstützt. Daher müssen die Tests gegen Junit4 geschrieben und die Tests mit PowerMockRunner ausgeführt werden.
Um PowerMockRunner verwenden zu können, muss die Testklasse mit Anmerkungen versehen werden @RunWith (PowerMockRunner.class)
Lassen Sie uns nun diskutieren, private, statische und nichtige Methoden im Detail verspotten!
Private Methoden verspotten
Das Verspotten privater Methoden, die intern von einer getesteten Methode aufgerufen werden, kann zu bestimmten Zeiten unvermeidbar sein. Mit powermockito ist dies möglich und die Überprüfung erfolgt mit einer neuen Methode namens 'verifyPrivate'.
Lass uns nehmen einBeispiel Dabei ruft die zu testende Methode eine private Methode auf (die einen Booleschen Wert zurückgibt). Damit diese Methode je nach Test true / false zurückgibt, muss für diese Klasse ein Stub eingerichtet werden.
In diesem Beispiel wird die zu testende Klasse als Spionageinstanz erstellt, bei der nur wenige Schnittstellenaufrufe und private Methodenaufrufe verspottet werden.
Wichtige Punkte zur Mock Private Method:
# 1) Die Testmethode oder Testklasse muss mit @ versehen werden PrepareForTest (ClassUnderTest). Diese Anmerkung weist powerMockito an, bestimmte Klassen für das Testen vorzubereiten.
Dies sind hauptsächlich die Klassen, die es sein müssen Bytecode manipuliert . In der Regel für Abschlussklassen Klassen, die private und / oder statische Methoden enthalten, die während des Tests verspottet werden müssen.
Beispiel:
@PrepareForTest(PriceCalculator.class)
#zwei) So richten Sie einen Stub für eine private Methode ein
Syntax - - when (Schein- oder Spionageinstanz, 'privateMethodName'). thenReturn (// Rückgabewert)
Beispiel:
when (priceCalculatorSpy, 'isCustomerAnonymous').thenReturn(false);
#3) So überprüfen Sie die gestoppelte private Methode
Syntax - verifyPrivate (mockedInstance) .invoke ('privateMethodName')
Beispiel:
verifyPrivate (priceCalculator).invoke('isCustomerAnonymous');
Vollständiges Testmuster: Fortsetzung des gleichen Beispiels aus den vorherigen Artikeln, in denen priceCalculator einige verspottete Abhängigkeiten wie itemService, userService usw. aufweist.
Wir haben eine neue Methode namens 'berechnePreisWithPrivatMethode' erstellt, die eine private Methode innerhalb derselben Klasse aufruft und zurückgibt, ob der Kunde anonym ist oder nicht.
@Test @PrepareForTest(PriceCalculator.class) public void calculatePriceForAnonymous_witStubbedPrivateMethod_returnsCorrectPrice() throws Exception { // Arrange ItemSku item1 = new ItemSku(); item1.setApplicableDiscount(5.00); item1.setPrice(100.00); double expectedPrice = 90.00; // Setting up stubbed responses using mocks when(priceCalculatorSpy, 'isCustomerAnonymous').thenReturn(false); when(mockedItemService.getItemDetails(123)).thenReturn(item1); // Act double actualDiscountedPrice = priceCalculatorSpy.calculatePriceWithPrivateMethod(123); // Assert verifyPrivate(priceCalculator).invoke('isCustomerAnonymous'); assertEquals(expectedPrice, actualDiscountedPrice); }
Statische Methoden verspotten
Statische Methoden können auf ähnliche Weise verspottet werden, wie wir es für die privaten Methoden gesehen haben.
Wenn eine zu testende Methode die Verwendung einer statischen Methode aus derselben Klasse (oder aus einer anderen Klasse) umfasst, müssen wir diese Klasse vor dem Test (oder in der Testklasse) in die Annotation prepareForTest aufnehmen.
Wichtige Punkte zu Mock Static Methods:
# 1) Die Testmethode oder Testklasse muss mit @ versehen werden PrepareForTest (ClassUnderTest). Ähnlich wie beim Verspotten privater Methoden / Klassen ist dies auch für statische Klassen erforderlich.
#zwei) Ein zusätzlicher Schritt, der für statische Methoden erforderlich ist, ist - mockStatic (// Name der statischen Klasse)
Beispiel:
mockStatic(DiscountCategoryFinder.class)
#3) Das Einrichten von Stubs für eine statische Methode ist so gut wie das Stubben von Methoden für andere Schnittstellen- / Klassen-Mock-Instanzen.
Zum Beispiel: Um die statische Methode der DiscountCategoryFinder-Klasse getDiscountCategory () (die eine Aufzählung DiscountCategory mit den Werten PREMIUM & GENERAL zurückgibt) zu stubben, stubben Sie einfach wie folgt:
when (DiscountCategoryFinder. getDiscountCategory ()).thenReturn(DiscountCategory. PREMIUM );
# 4) Um das Mock-Setup für die endgültige / statische Methode zu überprüfen, kann die Methode verifyStatic () verwendet werden.
Beispiel:
verifyStatic (DiscountCategoryFinder.class, times (1));
Voiding-Methoden verspotten
Versuchen wir zunächst zu verstehen, welche Art von Anwendungsfällen das Stubben von Void-Methoden beinhalten könnten:
# 1) Zum Beispiel Methodenaufrufe, die während des Vorgangs eine E-Mail-Benachrichtigung senden.
Zum Beispiel ::Angenommen, Sie ändern Ihr Passwort für Ihr Internetbanking-Konto. Nach erfolgreicher Änderung erhalten Sie eine Benachrichtigung über Ihre E-Mail.
Dies kann als / changePassword als POST-Aufruf der Bank-API betrachtet werden, der einen Aufruf der void-Methode zum Senden einer E-Mail-Benachrichtigung an den Kunden enthält.
#zwei) Ein weiteres häufiges Beispiel für den Aufruf der void-Methode sind aktualisierte Anforderungen an eine Datenbank, die Eingaben vornehmen und nichts zurückgeben.
Stubbing-Void-Methoden (d. H. Methoden, die nichts zurückgeben oder eine Ausnahme auslösen) können mit behandelt werden Funktionen doNothing (), doThrow () und doAnswer (), doCallRealMethod () . Der Stub muss gemäß den Testerwartungen mit den oben genannten Methoden eingerichtet werden.
Beachten Sie außerdem, dass alle Aufrufe der void-Methode standardmäßig mit doNothing () verspottet sind. Selbst wenn ein explizites Mock-Setup nicht durchgeführt wird LEERE Methodenaufrufe lautet das Standardverhalten weiterhin doNothing ().
Sehen wir uns Beispiele für all diese Funktionen an:
Nehmen wir für alle Beispiele an, dass es eine Klasse gibt StudentScoreUpdates das hat eine Methode berechneSumAndStore (). Diese Methode berechnet die Summe der Punkte (als Eingabe) und ruft a auf Leere Methode updateScores () auf der Datenbankimplementierungsinstanz.
Ein Beispiel für eine funktionale Anforderung ist _________
public class StudentScoreUpdates { public IDatabase databaseImpl; public StudentScoreUpdates(IDatabase databaseImpl) { this.databaseImpl = databaseImpl; } public void calculateSumAndStore(String studentId, int() scores) { int total = 0; for(int score : scores) { total = total + score; } // write total to DB databaseImpl.updateScores(studentId, total); } }
Wir werden Unit-Tests für den Mock-Methodenaufruf mit den folgenden Beispielen schreiben:
# 1) doNothing () - doNothing () ist das Standardverhalten für Aufrufe der void-Methode in Mockito, d. H. Selbst wenn Sie einen Aufruf der void-Methode überprüfen (ohne explizit eine void für doNothing () einzurichten, ist die Überprüfung weiterhin erfolgreich).
public void calculateSumAndStore_withValidInput_shouldCalculateAndUpdateResultInDb() { // Arrange studentScores = new StudentScoreUpdates(mockDatabase); int() scores = {60,70,90}; Mockito.doNothing().when(mockDatabase).updateScores(anyString(), anyInt()); // Act studentScores.calculateSumAndStore('student1', scores); // Assert Mockito.verify(mockDatabase, Mockito.times(1)).updateScores(anyString(), anyInt()); }
Andere Verwendungen zusammen mit doNothing ()
zu) Wenn die void-Methode mehrmals aufgerufen wird und Sie unterschiedliche Antworten für unterschiedliche Aufrufe einrichten möchten, z. B. - doNothing () für den ersten Aufruf, und beim nächsten Aufruf eine Ausnahme auslösen möchten.
Zum Beispiel ::Stellen Sie das Modell so ein:
Mockito. doNothing ().doThrow(new RuntimeException()).when(mockDatabase).updateScores( anyString (), anyInt ());
b) Wenn Sie die Argumente erfassen möchten, mit denen die void-Methode aufgerufen wurde, sollte die ArgumentCaptor-Funktionalität in Mockito verwendet werden. Dies gibt eine zusätzliche Überprüfung der Argumente, mit denen die Methode aufgerufen wurde.
Beispiel mit ArgumentCaptor:
public void calculateSumAndStore_withValidInput_shouldCalculateAndUpdateResultInDb() { // Arrange studentScores = new StudentScoreUpdates(mockDatabase); int() scores = {60,70,90}; Mockito.doNothing().when(mockDatabase).updateScores(anyString(), anyInt()); ArgumentCaptor studentIdArgument = ArgumentCaptor.forClass(String.class); // Act studentScores.calculateSumAndStore('Student1', scores); // Assert Mockito.verify(mockDatabase, Mockito.times(1)).updateScores(studentIdArgument.capture(), anyInt()); assertEquals('Student1', studentIdArgument.getValue()); }
# 2) doThrow ()- - Dies ist nützlich, wenn Sie einfach eine Ausnahme auslösen möchten, wenn die void-Methode von der zu testenden Methode aufgerufen wird.
Zum Beispiel:
Mockito.doThrow(newRuntimeException()).when(mockDatabase).updateScores ( anyString (), anyInt ());
# 3) doAnswer ()- - doAnswer () bietet einfach eine Schnittstelle für benutzerdefinierte Logik.
Z.B. Ändern eines Werts durch die übergebenen Argumente, Zurückgeben von benutzerdefinierten Werten / Daten, die ein normaler Stub insbesondere für void-Methoden nicht hätte zurückgeben können.
Zu Demonstrationszwecken habe ich die void-Methode updateScores () blockiert, um ein ' Antworten() ”Und drucken Sie den Wert eines der Argumente, die beim Aufruf der Methode übergeben werden sollten.
Codebeispiel:
@Test public void calculateSumAndStore_withValidInput_shouldCalculateAndUpdateResultInDb() { // Arrange studentScores = new StudentScoreUpdates(mockDatabaseImpl); int() scores = {60,70,90}; Mockito.doCallRealMethod().when(mockDatabaseImpl).updateScores(anyString(), anyInt()); doAnswer(invocation -> { Object() args = invocation.getArguments(); Object mock = invocation.getMock(); System.out.println(args(0)); return mock; }).when(mockDatabaseImpl).updateScores(anyString(), anyInt()); // Act studentScores.calculateSumAndStore('Student1', scores); // Assert Mockito.verify(mockDatabaseImpl, Mockito.times(1)).updateScores(anyString(), anyInt()); }
# 4) doCallRealMethod ()- - Partielle Mocks ähneln Stubs (bei denen Sie für einige Methoden echte Methoden aufrufen und den Rest stubben können).
Für void-Methoden bietet mockito eine spezielle Funktion namens doCallRealMethod (), die verwendet werden kann, wenn Sie versuchen, das mock einzurichten. Dies wird dazu führen, dass die echte Void-Methode mit den tatsächlichen Argumenten aufgerufen wird.
Zum Beispiel:
Mockito. doCallRealMethod ().when(mockDatabaseImpl).updateScores( anyString (), anyInt ());
Tipps
# 1) Einschließen mehrerer statischer Klassen in dieselbe Testmethode / Klasse- Verwenden von PowerMockito Wenn mehrere Static of Final-Klassen verspottet werden müssen, werden die Klassennamen in @ PrepareForTest Annotation kann als durch Kommas getrennter Wert als Array erwähnt werden (sie akzeptiert im Wesentlichen ein Array der Klassennamen).
Beispiel:
@PrepareForTest({PriceCalculator.class, DiscountCategoryFinder.class})
Nehmen Sie an, wie im obigen Beispiel gezeigt, dass sowohl PriceCalculator als auch DiscountCategoryFinder endgültige Klassen sind, die verspottet werden müssen. Beide können als Array von Klassen in der PrepareForTest-Annotation erwähnt und in der Testmethode gestoppt werden.
# 2) PrepareForTest-Attribut Positionierung - Die Positionierung dieses Attributs ist wichtig für die Art der Tests, die in der Testklasse enthalten sind.
Wenn für alle Tests dieselbe Abschlussklasse verwendet werden muss, ist es sinnvoll, dieses Attribut auf Testklassenebene zu erwähnen. Dies bedeutet lediglich, dass die vorbereitete Klasse allen Testmethoden zur Verfügung steht. Im Gegensatz dazu steht die Anmerkung, wenn sie in der Testmethode erwähnt wird, nur diesen bestimmten Tests zur Verfügung
Fazit
In diesem Tutorial haben wir verschiedene Ansätze diskutiert, um statische, endgültige und nichtige Methoden zu verspotten.
Obwohl die Verwendung vieler statischer oder endgültiger Methoden die Testbarkeit beeinträchtigt, gibt es Unterstützung für das Testen / Verspotten, um beim Erstellen von Komponententests zu helfen, um ein größeres Vertrauen in den Code / die Anwendung zu erreichen, selbst für Legacy-Code, der im Allgemeinen nicht verwendet wird auf Testbarkeit ausgelegt sein.
Für statische und endgültige Methoden bietet Mockito keine sofort einsatzbereite Unterstützung, aber Bibliotheken wie PowerMockito (die viele Dinge stark von Mockito erben) bieten diese Unterstützung und müssen tatsächlich eine Bytecode-Manipulation durchführen, um diese Funktionen zu unterstützen.
Mockito out of the box unterstützt Stubbing-Void-Methoden und bietet verschiedene Methoden wie doNothing, doAnswer, doThrow, doCallRealMethod usw. und kann gemäß den Anforderungen des Tests verwendet werden.
Die am häufigsten gestellten Fragen zum Mockito-Interview werden in unserem nächsten Tutorial behandelt.
PREV Tutorial | NÄCHSTES Tutorial
Literatur-Empfehlungen
- Mockito Tutorial: Mockito Framework zum Verspotten im Unit Testing
- Top 12 Fragen zum Mockito-Interview (Mocking Framework-Interview)
- Statisch In C ++
- Java-Threads mit Methoden und Lebenszyklus
- Erstellen von Mocks und Spionen in Mockito mit Codebeispielen
- Verschiedene Arten von Matchern von Mockito
- Methoden und Techniken zur Fehlervermeidung
- Verwendung von Methoden in SoapUI für die Ausführung von Massentests - SoapUI Tutorial # 10