Einführung in PowerMock

1. Übersicht

Unit-Tests mit Hilfe eines Mocking-Frameworks haben sich seit langem als nützliche Praxis erwiesen, und insbesondere das Mockito-Framework hat diesen Markt in den letzten Jahren dominiert.

Und um anständige Code-Designs zu ermöglichen und die öffentliche API zu vereinfachen, wurden einige gewünschte Funktionen absichtlich weggelassen. In einigen Fällen zwingen diese Mängel die Tester jedoch dazu, umständlichen Code zu schreiben, um die Erstellung von Mocks zu ermöglichen.

Hier kommt das PowerMock-Framework ins Spiel.

PowerMockito ist eine PowerMock-Erweiterungs-API zur Unterstützung von Mockito. Es bietet Funktionen zum einfachen Arbeiten mit der Java Reflection-API, um die Probleme von Mockito zu überwinden, z. B. die mangelnde Fähigkeit, endgültige, statische oder private Methoden zu verspotten.

Dieses Tutorial enthält eine Einführung in die PowerMockito-API und deren Anwendung in Tests.

2. Vorbereitung zum Testen mit PowerMockito

Der erste Schritt zur Integration der PowerMock-Unterstützung für Mockito besteht darin, die folgenden zwei Abhängigkeiten in die Maven POM-Datei aufzunehmen:

 org.powermock powermock-module-junit4 1.6.4 test   org.powermock powermock-api-mockito 1.6.4 test 

Als Nächstes müssen wir unsere Testfälle für die Arbeit mit PowerMockito vorbereiten, indem wir die folgenden zwei Anmerkungen anwenden:

@RunWith(PowerMockRunner.class) @PrepareForTest(fullyQualifiedNames = "com.baeldung.powermockito.introduction.*")

Das Element fullQualifiedNames in der Annotation @PrepareForTest repräsentiert ein Array vollständig qualifizierter Namen von Typen, die verspottet werden sollen. In diesem Fall verwenden wir einen Paketnamen mit einem Platzhalter, um PowerMockito anzuweisen , alle Typen im Paket com.baeldung.powermockito.introduction für das Verspotten vorzubereiten .

Jetzt sind wir bereit, die Leistung von PowerMockito zu nutzen .

3. Verspottungskonstruktoren und endgültige Methoden

In diesem Abschnitt zeigen wir, wie Sie beim Instanziieren einer Klasse mit dem neuen Operator eine Scheininstanz anstelle einer echten Instanz abrufen und dieses Objekt dann zum Verspotten einer endgültigen Methode verwenden. Die kollaborierende Klasse, deren Konstruktoren und endgültige Methoden verspottet werden, ist wie folgt definiert:

public class CollaboratorWithFinalMethods { public final String helloMethod() { return "Hello World!"; } }

Zuerst erstellen wir ein Scheinobjekt mit der PowerMockito- API:

CollaboratorWithFinalMethods mock = mock(CollaboratorWithFinalMethods.class);

Legen Sie als Nächstes eine Erwartung fest, die besagt, dass bei jedem Aufruf des Konstruktors ohne Argumente dieser Klasse eine Scheininstanz zurückgegeben werden sollte und keine echte:

whenNew(CollaboratorWithFinalMethods.class).withNoArguments().thenReturn(mock);

Lassen Sie uns sehen, wie diese Konstruktionsverspottung in Aktion funktioniert, indem Sie die CollaboratorWithFinalMethods- Klasse mit ihrem Standardkonstruktor instanziieren und dann das Verhalten von PowerMock überprüfen:

CollaboratorWithFinalMethods collaborator = new CollaboratorWithFinalMethods(); verifyNew(CollaboratorWithFinalMethods.class).withNoArguments();

Im nächsten Schritt wird eine Erwartung auf die endgültige Methode gesetzt:

when(collaborator.helloMethod()).thenReturn("Hello Baeldung!");

Diese Methode wird dann ausgeführt:

String welcome = collaborator.helloMethod();

Die folgenden Zusicherungen bestätigen, dass die helloMethod- Methode für das Collaborator- Objekt aufgerufen wurde , und geben den durch die Verspottungserwartung festgelegten Wert zurück:

Mockito.verify(collaborator).helloMethod(); assertEquals("Hello Baeldung!", welcome);

Wenn wir eine bestimmte endgültige Methode verspotten möchten und nicht alle endgültigen innerhalb eines Objekts, kann die Methode Mockito.spy (T-Objekt) nützlich sein. Dies ist in Abschnitt 5 dargestellt.

4. Verspotten statischer Methoden

Angenommen, wir möchten statische Methoden einer Klasse namens CollaboratorWithStaticMethods verspotten . Diese Klasse wird wie folgt deklariert:

public class CollaboratorWithStaticMethods { public static String firstMethod(String name) { return "Hello " + name + " !"; } public static String secondMethod() { return "Hello no one!"; } public static String thirdMethod() { return "Hello no one again!"; } }

Um diese statischen Methoden zu verspotten, müssen wir die einschließende Klasse bei der PowerMockito- API registrieren :

mockStatic(CollaboratorWithStaticMethods.class);

Alternativ können wir die Methode Mockito.spy (Klassenklasse) verwenden, um eine bestimmte Methode zu verspotten, wie im folgenden Abschnitt gezeigt.

Als nächstes können Erwartungen festgelegt werden, um die Werte zu definieren, die Methoden beim Aufrufen zurückgeben sollen:

when(CollaboratorWithStaticMethods.firstMethod(Mockito.anyString())) .thenReturn("Hello Baeldung!"); when(CollaboratorWithStaticMethods.secondMethod()).thenReturn("Nothing special");

Oder es kann eine Ausnahme festgelegt werden, die beim Aufrufen der Drittmethode ausgelöst wird:

doThrow(new RuntimeException()).when(CollaboratorWithStaticMethods.class); CollaboratorWithStaticMethods.thirdMethod();

Jetzt ist es Zeit, die ersten beiden Methoden auszuführen:

String firstWelcome = CollaboratorWithStaticMethods.firstMethod("Whoever"); String secondWelcome = CollaboratorWithStaticMethods.firstMethod("Whatever");

Anstatt Mitglieder der realen Klasse aufzurufen, werden die obigen Aufrufe an die Methoden des Mocks delegiert. Die folgenden Behauptungen beweisen, dass der Schein in Kraft getreten ist:

assertEquals("Hello Baeldung!", firstWelcome); assertEquals("Hello Baeldung!", secondWelcome);

Wir können auch das Verhalten der Methoden des Mocks überprüfen, einschließlich der Häufigkeit, mit der eine Methode aufgerufen wird. In diesem Fall wurde die erste Methode zweimal aufgerufen, während die zweite Methode niemals:

verifyStatic(Mockito.times(2)); CollaboratorWithStaticMethods.firstMethod(Mockito.anyString()); verifyStatic(Mockito.never()); CollaboratorWithStaticMethods.secondMethod();

Hinweis: Die verifyStatic- Methode muss unmittelbar vor jeder statischen Methodenüberprüfung aufgerufen werden, damit PowerMockito weiß, dass der nachfolgende Methodenaufruf überprüft werden muss.

Lastly, the static thirdMethod method should throw a RuntimeException as declared on the mock before. It is validated by the expected element of the @Test annotation:

@Test(expected = RuntimeException.class) public void givenStaticMethods_whenUsingPowerMockito_thenCorrect() { // other methods CollaboratorWithStaticMethods.thirdMethod(); }

5. Partial Mocking

Instead of mocking an entire class, the PowerMockito API allows for mocking part of it using the spy method. The following class will be used as the collaborator to illustrate the PowerMock support for partial mocking:

public class CollaboratorForPartialMocking { public static String staticMethod() { return "Hello Baeldung!"; } public final String finalMethod() { return "Hello Baeldung!"; } private String privateMethod() { return "Hello Baeldung!"; } public String privateMethodCaller() { return privateMethod() + " Welcome to the Java world."; } }

Let's begin with mocking a static method, which is named staticMethod in the above class definition. First, use the PowerMockito API to partially mock the CollaboratorForPartialMocking class and set an expectation for its static method:

spy(CollaboratorForPartialMocking.class); when(CollaboratorForPartialMocking.staticMethod()).thenReturn("I am a static mock method.");

The static method is then executed:

returnValue = CollaboratorForPartialMocking.staticMethod();

The mocking behavior is verified as follows:

verifyStatic(); CollaboratorForPartialMocking.staticMethod();

The following assertion confirms that the mock method has actually been called by comparing the return value against the expectation:

assertEquals("I am a static mock method.", returnValue);

Now it is time to move on to the final and private methods. In order to illustrate the partial mocking of these methods, we need to instantiate the class and tell the PowerMockito API to spy it:

CollaboratorForPartialMocking collaborator = new CollaboratorForPartialMocking(); CollaboratorForPartialMocking mock = spy(collaborator);

The objects created above are used to demonstrating the mocking of both the final and private methods. We will deal with the final method now by setting an expectation and invoke the method:

when(mock.finalMethod()).thenReturn("I am a final mock method."); returnValue = mock.finalMethod();

The behavior of partially mocking that method is proved:

Mockito.verify(mock).finalMethod();

A test verifies that calling the finalMethod method will return a value that matches the expectation:

assertEquals("I am a final mock method.", returnValue);

A similar process is applied to the private method. The main difference is that we cannot directly invoke this method from the test case. Basically, a private method is to be called by other ones from the same class. In the CollaboratorForPartialMocking class, the privateMethod method is to be invoked by the privateMethodCaller method and we will use the latter as a delegate. Let's start with the expectation and invocation:

when(mock, "privateMethod").thenReturn("I am a private mock method."); returnValue = mock.privateMethodCaller();

The mocking of the private method is confirmed:

verifyPrivate(mock).invoke("privateMethod");

The following test makes sure that the return value from invocation of the private method is the same as the expectation:

assertEquals("I am a private mock method. Welcome to the Java world.", returnValue);

6. Conclusion

Dieses Tutorial bietet eine Einführung in die PowerMockito- API und demonstriert deren Verwendung bei der Lösung einiger Probleme, auf die Entwickler bei der Verwendung des Mockito-Frameworks stoßen.

Die Implementierung dieser Beispiele und Codefragmente finden Sie im verknüpften GitHub-Projekt.