Was ist der Unterschied zwischen Spott und Spionage bei der Verwendung von Mockito?
137
Was wäre ein Anwendungsfall für die Verwendung eines Mockito-Spions?
Es scheint mir, dass jeder Spionage-Anwendungsfall mit callRealMethod mit einem Mock behandelt werden kann.
Ein Unterschied, den ich sehen kann, ist, wenn Sie möchten, dass die meisten Methodenaufrufe real sind, werden einige Codezeilen gespeichert, um einen Schein gegen einen Spion zu verwenden. Ist es das oder fehlt mir das Gesamtbild?
Nach vielen internen Debatten und Diskussionen auf der Mailingliste wurde Mockito schließlich eine teilweise Scheinunterstützung hinzugefügt. Bisher haben wir Partial Mocks als Code-Gerüche betrachtet. Wir haben jedoch einen legitimen Anwendungsfall für partielle Verspottungen gefunden.
Vor Release 1.8 produzierte spy () keine echten Partial Mocks und es war für einige Benutzer verwirrend. Lesen Sie mehr über Spionage: hier oder in javadoc für die Spionagemethode (Objekt).
callRealMethod()wurde nach eingeführt spy(), aber spy () wurde natürlich dort gelassen, um die Abwärtskompatibilität sicherzustellen.
Ansonsten haben Sie Recht: Alle Methoden eines Spions sind real, sofern sie nicht gestoppt werden. Alle Methoden eines Mocks werden gestoppt, sofern sie nicht callRealMethod()aufgerufen werden. Im Allgemeinen würde ich es vorziehen, zu verwenden callRealMethod(), da es mich nicht zwingt, die doXxx().when()Redewendung anstelle der traditionellen zu verwendenwhen().thenXxx()
Das Problem bei der Bevorzugung von Mock gegenüber Spion besteht in diesen Fällen darin, dass die Klasse ein Mitglied verwendet, das nicht in sie injiziert (sondern lokal initialisiert) ist und später von der "echten" Methode verwendet wird. Im Mock wird das Mitglied auf seinen Standard-Java-Wert initialisiert, was zu falschem Verhalten oder sogar einer NullPointerException führen kann. Der Weg, dies zu übergeben, besteht darin, eine "init" -Methode hinzuzufügen und sie dann "wirklich" aufzurufen, aber das scheint mir ein bisschen übertrieben zu sein.
Eyal Roth
Aus dem Dokument: "Spione sollten sorgfältig und gelegentlich eingesetzt werden, beispielsweise beim Umgang mit Legacy-Code." Der Einheitentestraum leidet unter zu vielen Möglichkeiten, dasselbe zu tun.
GDBJ
89
Unterschied zwischen einem Spion und einem Mock
Wenn Mockito ein Modell erstellt, geschieht dies aus der Klasse eines Typs und nicht aus einer tatsächlichen Instanz. Der Mock erstellt einfach eine Bare-Bones-Shell-Instanz der Klasse, die vollständig instrumentiert ist, um Interaktionen mit ihr zu verfolgen. Auf der anderen Seite wird der Spion eine vorhandene Instanz umschließen. Es verhält sich immer noch genauso wie die normale Instanz - der einzige Unterschied besteht darin, dass es auch instrumentiert wird, um alle Interaktionen mit ihm zu verfolgen.
Im folgenden Beispiel erstellen wir ein Modell der ArrayList-Klasse:
Wie Sie sehen können - das Hinzufügen eines Elements zur verspotteten Liste fügt eigentlich nichts hinzu - ruft die Methode nur ohne weitere Nebenwirkungen auf. Ein Spion hingegen verhält sich anders - er ruft tatsächlich die eigentliche Implementierung der Methode add auf und fügt das Element der zugrunde liegenden Liste hinzu:
Hier können wir sicherlich sagen, dass die reale interne Methode des Objekts aufgerufen wurde, denn wenn Sie die size () -Methode aufrufen, erhalten Sie die Größe als 1, aber diese size () -Methode wurde nicht verspottet! Woher komme ich? Die interne Methode real size () wird aufgerufen, da size () nicht verspottet (oder gestoppt) wird. Daher können wir sagen, dass der Eintrag dem realen Objekt hinzugefügt wurde.
Warum wird im ersten Beispiel mockedList.size()zurückgegeben, 0wenn diese Methode auch nicht ausgeblendet wurde? Ist das nur ein Standardwert angesichts des Rückgabetyps der Methode?
Mike
@mike: Gibt mockedList.size()einen zurück intund der Standardwert von intist in Java 0. Wenn Sie versuchen, assertEquals(0, mockedList.size());danach auszuführen mockedList.clear();, bleibt das Ergebnis gleich.
RealPK
2
Diese Antwort ist gut und einfach geschrieben und hat mir geholfen, endlich den Unterschied zwischen Schein und Spion zu verstehen. Schön.
PesaDer
38
Wenn es ein Objekt mit 8 Methoden gibt und Sie einen Test haben, bei dem Sie 7 echte Methoden aufrufen und eine Methode stubben möchten, haben Sie zwei Möglichkeiten:
Mit einem Mock müssten Sie es einrichten, indem Sie 7 callRealMethod aufrufen und eine Methode stubben
Mit a müssen spySie es einrichten, indem Sie eine Methode stubben
Die offizielle Dokumentation über doCallRealMethodempfiehlt einen Spion für die partielle Mocks verwenden.
Siehe auch javadoc spy (Object), um mehr über partielle Verspottungen zu erfahren. Mockito.spy () ist eine empfohlene Methode zum Erstellen von Teil-Mocks. Der Grund dafür ist, dass garantiert wird, dass echte Methoden für korrekt erstellte Objekte aufgerufen werden, da Sie für die Erstellung des an die spy () -Methode übergebenen Objekts verantwortlich sind.
Mockist ein nacktes Doppelobjekt. Dieses Objekt hat die gleichen Methodensignaturen, aber die Realisierung ist leer und gibt den Standardwert 0 und null zurück
Spyist ein geklontes Doppelobjekt. Neues Objekt wird basierend auf einem realen Objekt geklont, aber Sie haben die Möglichkeit, es zu verspotten
class A {String foo1(){
foo2();return"RealString_1";}String foo2(){return"RealString_2";}void foo3(){
foo4();}void foo4(){}}
Unterschied zwischen einem Spion und einem Mock
Wenn Mockito ein Modell erstellt, geschieht dies aus der Klasse eines Typs und nicht aus einer tatsächlichen Instanz. Der Mock erstellt einfach eine Bare-Bones-Shell-Instanz der Klasse, die vollständig instrumentiert ist, um Interaktionen mit ihr zu verfolgen. Auf der anderen Seite wird der Spion eine vorhandene Instanz umschließen. Es verhält sich immer noch genauso wie die normale Instanz - der einzige Unterschied besteht darin, dass es auch instrumentiert wird, um alle Interaktionen mit ihm zu verfolgen.
Im folgenden Beispiel erstellen wir ein Modell der ArrayList-Klasse:
Wie Sie sehen können - das Hinzufügen eines Elements zur verspotteten Liste fügt eigentlich nichts hinzu - ruft die Methode nur ohne weitere Nebenwirkungen auf. Ein Spion hingegen verhält sich anders - er ruft tatsächlich die eigentliche Implementierung der Methode add auf und fügt das Element der zugrunde liegenden Liste hinzu:
Hier können wir sicherlich sagen, dass die reale interne Methode des Objekts aufgerufen wurde, denn wenn Sie die size () -Methode aufrufen, erhalten Sie die Größe als 1, aber diese size () -Methode wurde nicht verspottet! Woher komme ich? Die interne Methode real size () wird aufgerufen, da size () nicht verspottet (oder gestoppt) wird. Daher können wir sagen, dass der Eintrag dem realen Objekt hinzugefügt wurde.
Quelle: http://www.baeldung.com/mockito-spy + Selbstnotizen.
quelle
mockedList.size()
zurückgegeben,0
wenn diese Methode auch nicht ausgeblendet wurde? Ist das nur ein Standardwert angesichts des Rückgabetyps der Methode?mockedList.size()
einen zurückint
und der Standardwert vonint
ist in Java 0. Wenn Sie versuchen,assertEquals(0, mockedList.size());
danach auszuführenmockedList.clear();
, bleibt das Ergebnis gleich.Wenn es ein Objekt mit 8 Methoden gibt und Sie einen Test haben, bei dem Sie 7 echte Methoden aufrufen und eine Methode stubben möchten, haben Sie zwei Möglichkeiten:
spy
Sie es einrichten, indem Sie eine Methode stubbenDie offizielle Dokumentation über
doCallRealMethod
empfiehlt einen Spion für die partielle Mocks verwenden.quelle
Spy kann nützlich sein, wenn Sie Komponententests für Legacy-Code erstellen möchten .
Ich habe hier ein ausführbares Beispiel erstellt: https://www.surasint.com/mockito-with-spy/ . Einige davon kopiere ich hier.
Wenn Sie so etwas wie diesen Code haben:
Möglicherweise benötigen Sie keinen Spion, da Sie nur DepositMoneyService und WithdrawMoneyService verspotten können.
Bei einigen Legacy-Codes ist die Abhängigkeit jedoch wie folgt im Code:
Ja, Sie können zum ersten Code wechseln, aber dann wird die API geändert. Wenn diese Methode von vielen Orten verwendet wird, müssen Sie alle ändern.
Alternativ können Sie die Abhängigkeit folgendermaßen extrahieren:
Dann können Sie den Spion verwenden, um die Abhängigkeit wie folgt zu injizieren:
Weitere Details im obigen Link.
quelle
Mock
ist ein nacktes Doppelobjekt. Dieses Objekt hat die gleichen Methodensignaturen, aber die Realisierung ist leer und gibt den Standardwert 0 und null zurückSpy
ist ein geklontes Doppelobjekt. Neues Objekt wird basierend auf einem realen Objekt geklont, aber Sie haben die Möglichkeit, es zu verspotten[Doppeltypen testen]
quelle