Mockito: Verify: Unterschied zwischen den Versionen

Aus MimiPedia
(Die Seite wurde neu angelegt: „Kategorie:Java Kategorie:Mockito = Mock vs. Spy = Neben dem hier beschriebenen Mocks giebt es ein weiteres Konzept in Mockito, das dem Mocki sehr ähnl…“)
 
Keine Bearbeitungszusammenfassung
Zeile 1: Zeile 1:
[[Kategorie:Java]]
[[Kategorie:Java]]
[[Kategorie:Mockito]]
[[Kategorie:Mockito]]
= Mock vs. Spy =
== Voraussetzungen ==
Neben dem hier beschriebenen Mocks giebt es ein weiteres Konzept in Mockito, das dem Mocki sehr ähnlich ist: der Spy.
Die Voraussetzungen für die Anwendung von {{java|verify}} sind simpel.
Bei einem Spy handelt es sich um ein Objekt, das um ein anderes Objekt herumgewickelt wird. Gewöhnlich wird es verwendet
Man benötigt dazu einen Mock oder einen Spy der ein "echtes" Objekt umwickelt.
um Laufzeit-Informationen über das Objekt zu sammeln. Man kann damit etwa überprüfen, ob eine Methode des Objekts aufgerufen
Mocks und Spies werden [[Partieller Mock|hier]] beschrieben.
wurde oder nicht -- sehr praktisch in Unit-Tests. Ein Spy wird so erzeugt:
 
== Die grundsätzliche Anwendung ==
Wir stellen uns hier einen Handler vor, dessen {{java|onMessage}}-Methode die {{java|send}}-Methode
des {{java|WebSocketConnection}}-Objekts aufrufen soll.
{{java|code=
{{java|code=
Foo foo = new Foo();
@Test
Foo spiedFoo = Mockito.spy(foo);
public void auftragNullSendetFehlermeldung() {
    WebSocketConnection connection = Mockito.mock(WebSocketConnection.class);
    handler.onMessage(connection, (String) null);
    Mockito.verify(connection, Mockito.atLeastOnce()).send("Die Anfrage kann nicht verarbeitet werden.");
}}
}}
Im Gegensatz zum Mock benötigt der Spy für die Erzeugung ein Objekt. Das entstehende Spy-Objekt hat den gleichen Typ
Die ersten beiden Zeilen führen den Test durch, die dritte Zeile prüft, daß die {{java|send}}-Methode
wie das umwickelte Objekt. Wie der Mock entsteht dabei eine Unterklasse. Einen Mock braucht man nicht mit einem Spy zu
mit dem angegebenen Text mindestens einmal aufgerufen wird.
umwickeln, er hat bereits die gleiche Funktionalität die der Spy erzeugt. Im Folgenden geht es um die unterschiedliche
Verwendung von Mock und Spy, Für die Untersuchung des Aufrufverhaltens giebt es eine eigene Seite.


= Zwei extreme Mocks =
Der erste Parameter von {{java|verify}} ist das zu untersuchende Objekt. Der zweite Parameter giebt die das erwartete
Die Klasse, die hier mit der mock-Methode erzeugt wird
Ergebnis an. Auf das Ergebnis wird die Methode aufgerufen, deren Aufruf überprüft werden soll.
{{java|code=Echt mock = Mockito.mock(Echt.class);}}
ersetzt alle Methoden der Klasse {{java|Echt}} durch gemockte Methoden. Man kann also getrost von einem ''totalen Mock''
sprechen. Ein Objekt der Klasse {{java|Echt}} ist ein gewissermaßen ein ''echtes'' Objekt und hingegen erwartungsgemäß keine
einzige Methode der Klasse. Man könnte in ihr einen entartetetn Mock sehen und als ''Null-Mock'' bezeichnen.


Objekte der originalen Klasse können nicht unmittelbar mit Mockito manipuliert werden, man umwickelt sie daher mit
Das gleiche {{java|verify}} würde auch funktioneren, wenn statt des Mocks eine echte Connection erzeugt um mit spy
einem Mockito-Proxy-Objekt, einem Spy:
ummantelt würde:
{{java|code=Echt spy = Mockito.spy(new Echt());}}
{{java|code=WebSocketConnection connection = Mockito.spy(new MyWebSocketConnectionImplementation());}}
Zwischen diesen beiden Extremen, dem "Alles" des totalen Mock und dem "Nichts" des Null-Mock liegt ein weites
Feld von Möglichkeiten um Teile der Original-Klasse durch mock-Methoden zu ersetzt und Teile davon unberührt
zu lassen: das sind die partiellen Mocks.


Um einen partiellen Mock zu bauen gibt es zwei diametrale Vorgehensweisen: Entweder man beginnt beim totalen
== Prüfungen ==
Mock und läßt einzelne Methoden die Funktionalität der Original-Klasse ausführen; oder man beginnt beim Null-Mock
:'''atLeastOnce'''
und mockt einzelne Methoden, deren originale Funktionalität nicht ausgeführt werden soll. Für welches Vorgehen
:: Die Methode wurde mindestens einmal aufgerufen
man sich entscheidet hängt vom Anwendungsfall ab.


== Den totalen Mock aufweichen ==
:'''times(n)'''
die Klasse {{java|Echt}} sei so definiert:
:: Die Methode wurde ''n'' mal aufgerufen
{{java|code=
class Echt {
    int eins() {
        return 1;
    }
    int zwei(int x) {
        return x + 3;
    }
}
}}
Der eingangs erzeugte Mock mockt beide Methoden. Die Methode {{java|eins}} soll nun ''nicht mehr'' gemockt werden,
das geht so:
{{java|code=
Echt mock = Mockito.mock(Echt.class);
Mockito.when(mock.eins()).thenCallRealMethod();
}}
Mehr ist dazu eigentlich nicht zu sagen. Der Aufruf von {{java|eins()}} liefert nun wie erwartet den Wert ''1'', während der
Aufruf von {{java|zwei()}} für jedes Argument den Wert ''0'' liefert.
Man hat nun für jede Methode drei Möglichkeiten die man nach belieben anwenden kann:
*Nichts tun und die gemockte Methode behalten
*Die echte Methode der Superklasse aufrufen
*Die Methode mit speziellem Mock-Verhalten ausstatten
Die Mock-Anweisungen lassen sich beliebig mischen, wie dieses Beispiel mit Methode {{java|zwei}} der Klasse {{java|Echt}} zeigt:
{{java|code=
Echt mock = Mockito.mock(Echt.class);
Mockito.when(mock.drei(Mockito.anyInt())).thenCallRealMethod();
Mockito.when(mock.drei(Mockito.eq(5))).thenReturn(4711);
}}
Bei Aufruf von {{java|mock.zwei(5)}} erhalten wir den Wert ''4711'' aus dem Mock und in allen anderen Fällen das Ergebnis
der echten Methode. Auch hier ist zu beachten, daß allgemeinere Matcher vor spezielleren Matchern kommen.
In diesem Falle also {{java|.anyInt()}} vor {{java|.eq(5)}}.


== Den Null-Mock aushöhlen ==
:'''times(0)''' oder '''never()'''
Wir beginnen nun mit dem Spy, der als Null-Mock das komplette Original-Verhalten der Klasse {{java|Echt erhält}}.
:: Die Methode wurde nicht aufgerufen
Diesmal möchten wir die Methode {{java|eins}} mocken, während die Methode {{java|zwe)}} weiterhin das reale Verhalten aufweist:
{{java|code=
Echt spy= Mockito.spy(new Echt());
Mockito.when(spy.eins()).thenReturn(3);
}}
Und fertig ist die Laube.

Version vom 29. April 2021, 12:55 Uhr

Voraussetzungen

Die Voraussetzungen für die Anwendung von verify sind simpel. Man benötigt dazu einen Mock oder einen Spy der ein "echtes" Objekt umwickelt. Mocks und Spies werden hier beschrieben.

Die grundsätzliche Anwendung

Wir stellen uns hier einen Handler vor, dessen onMessage-Methode die send-Methode des WebSocketConnection-Objekts aufrufen soll.

@Test
public void auftragNullSendetFehlermeldung() {
    WebSocketConnection connection = Mockito.mock(WebSocketConnection.class);
    handler.onMessage(connection, (String) null);
    Mockito.verify(connection, Mockito.atLeastOnce()).send("Die Anfrage kann nicht verarbeitet werden.");

Die ersten beiden Zeilen führen den Test durch, die dritte Zeile prüft, daß die send-Methode mit dem angegebenen Text mindestens einmal aufgerufen wird.

Der erste Parameter von verify ist das zu untersuchende Objekt. Der zweite Parameter giebt die das erwartete Ergebnis an. Auf das Ergebnis wird die Methode aufgerufen, deren Aufruf überprüft werden soll.

Das gleiche verify würde auch funktioneren, wenn statt des Mocks eine echte Connection erzeugt um mit spy ummantelt würde:

WebSocketConnection connection = Mockito.spy(new MyWebSocketConnectionImplementation());

Prüfungen

atLeastOnce
Die Methode wurde mindestens einmal aufgerufen
times(n)
Die Methode wurde n mal aufgerufen
times(0) oder never()
Die Methode wurde nicht aufgerufen