Einführung in PowerMock

Einführung in PowerMock

1. Überblick

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

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

Hier kommt dasPowerMockFramework ins Spiel.

PowerMockito ist eine PowerMock-Erweiterungs-API zur Unterstützung von Mockito. Es bietet die Möglichkeit, auf einfache Weise mit der Java Reflection-API zu arbeiten, um die Probleme von Mockito zu überwinden, z. B. das Fehlen der Fähigkeit, endgültige, statische oder private Methoden zu verspotten.

Dieses Tutorial gibt 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 mitPowerMockito vorbereiten, indem wir die folgenden zwei Anmerkungen anwenden:

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

Das ElementfullyQualifiedNames 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, umPowerMockito anzuweisen, alle Typen innerhalb descom.example.powermockito.introduction-Pakets für das Verspotten vorzubereiten.

Jetzt sind wir bereit, die Potenz vonPowerMockito auszunutzen.

3. Verspottungskonstruktoren und endgültige Methoden

In diesem Abschnitt werden wir zeigen, wie Sie eine Scheininstanz anstelle einer echten Instanz erhalten, wenn Sie eine Klasse mit dem Operatornewinstanziieren, und dieses Objekt dann verwenden, um eine endgültige Methode zu verspotten. 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 API vonPowerMockito:

CollaboratorWithFinalMethods mock = mock(CollaboratorWithFinalMethods.class);

Stellen Sie als Nächstes eine Erwartung ein, die besagt, dass immer dann, wenn der Konstruktor no-arg dieser Klasse aufgerufen wird, eine Scheininstanz und keine echte Instanz zurückgegeben werden sollte:

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

Lassen Sie uns sehen, wie diese Konstruktionsverspottung in Aktion funktioniert, indem Sie dieCollaboratorWithFinalMethods-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 an die endgültige Methode gestellt:

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

Diese Methode wird dann ausgeführt:

String welcome = collaborator.helloMethod();

Die folgenden Aussagen bestätigen, dass diehelloMethod-Methode für dascollaborator-Objekt aufgerufen wurde, und geben den durch die Verspottungserwartung festgelegten Wert zurück:

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

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

4. Statische Methoden verspotten

Angenommen, wir möchten statische Methoden einer Klasse mit dem NamenCollaboratorWithStaticMethods.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 derPowerMockito-API registrieren:

mockStatic(CollaboratorWithStaticMethods.class);

Alternativ können wir dieMockito.spy(Class<T> class)-Methode verwenden, um eine bestimmte 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 example!");
when(CollaboratorWithStaticMethods.secondMethod()).thenReturn("Nothing special");

Oder es kann eine Ausnahme festgelegt werden, die beim Aufrufen der MethodethirdMethodausgelö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 oben genannten Aufrufe an die Methoden des Mocks delegiert. Die folgenden Behauptungen beweisen, dass der Schein in Kraft getreten ist:

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

Wir können auch das Verhalten der Mock-Methoden überprüfen, einschließlich der Häufigkeit, mit der eine Methode aufgerufen wird. In diesem Fall wurdefirstMethod zweimal aufgerufen, währendsecondMethod nie:

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

verifyStatic(Mockito.never());
CollaboratorWithStaticMethods.secondMethod();

Note: Die MethodeverifyStatic muss unmittelbar vor jeder statischen Methodenüberprüfung aufgerufen werden, damitPowerMockito weiß, dass der aufeinanderfolgende Methodenaufruf überprüft werden muss.

Schließlich sollte die statischethirdMethod-Methode einRuntimeException auslösen, wie zuvor im Mock deklariert. Es wird durch dasexpected-Element der@Test-Annotation validiert:

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

    CollaboratorWithStaticMethods.thirdMethod();
}

5. Teilweise Verspottung

Anstatt eine ganze Klasse zu verspotten, ermöglicht die API vonPowerMockitodas Verspotten eines Teils davon mithilfe der Methodespy. Die folgende Klasse wird als Mitbearbeiter verwendet, um die PowerMock-Unterstützung für partielles Verspotten zu veranschaulichen:

public class CollaboratorForPartialMocking {
    public static String staticMethod() {
        return "Hello example!";
    }

    public final String finalMethod() {
        return "Hello example!";
    }

    private String privateMethod() {
        return "Hello example!";
    }

    public String privateMethodCaller() {
        return privateMethod() + " Welcome to the Java world.";
    }
}

Beginnen wir mit dem Verspotten einer statischen Methode, die in der obigen KlassendefinitionstaticMethod heißt. Verwenden Sie zunächst die APIPowerMockito, um die KlasseCollaboratorForPartialMockingteilweise zu verspotten und eine Erwartung für ihre statische Methode festzulegen:

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

Die statische Methode wird dann ausgeführt:

returnValue = CollaboratorForPartialMocking.staticMethod();

Das Spottverhalten wird wie folgt überprüft:

verifyStatic();
CollaboratorForPartialMocking.staticMethod();

Die folgende Zusicherung bestätigt, dass die Mock-Methode tatsächlich aufgerufen wurde, indem der Rückgabewert mit der Erwartung verglichen wird:

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

Nun ist es an der Zeit, zu den endgültigen und privaten Methoden überzugehen. Um die teilweise Verspottung dieser Methoden zu veranschaulichen, müssen wir die Klasse instanziieren und derPowerMockito APIspy it mitteilen:

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

Die oben erstellten Objekte werden verwendet, um das Verspotten der finalen und der privaten Methode zu demonstrieren. Wir werden uns nun mit der endgültigen Methode befassen, indem wir eine Erwartung setzen und die Methode aufrufen:

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

Das Verhalten, diese Methode teilweise zu verspotten, ist bewiesen:

Mockito.verify(mock).finalMethod();

Ein Test überprüft, ob der Aufruf der MethodefinalMethodeinen Wert zurückgibt, der der Erwartung entspricht:

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

Ein ähnlicher Prozess wird auf die private Methode angewendet. Der Hauptunterschied besteht darin, dass wir diese Methode nicht direkt aus dem Testfall aufrufen können. Grundsätzlich ist eine private Methode von anderen aus derselben Klasse aufzurufen. In der KlasseCollaboratorForPartialMocking soll die MethodeprivateMethod von der MethodeprivateMethodCaller aufgerufen werden, und wir werden letztere als Delegat verwenden. Beginnen wir mit der Erwartung und dem Aufruf:

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

Die Verspottung der privaten Methode wird bestätigt:

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

Der folgende Test stellt sicher, dass der Rückgabewert beim Aufrufen der privaten Methode mit der Erwartung übereinstimmt:

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

6. Fazit

Dieses Tutorial enthält eine Einführung in diePowerMockito-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 inthe linked GitHub project.