Ein Spion erstellt eine flache Kopie der Felder des übergebenen Objekts. Mocks verwenden keine normalen Konstruktoren oder Initialisierer, so dass in einem normalen Mockito-Mock alle Felder in ihrem Standardzustand bleiben (0, null, false usw.). Dies kann es schwierig machen, echte Methoden für einen Schein aufzurufen, da viele Instanzmethoden mit einigen ihrer Instanzen interagieren und nicht initialisierte Felder oft ungültig sind. Durch das Erlauben einer normalen Konstruktion und das anschließende Kopieren des Zustands kann sich ein Spy-Objekt fast genau wie ein normales Objekt verhalten - mit Ausnahme der Stubbing- und Verifikationsfunktionen, die Mockito bietet.
Obwohl Sie einen normalen Mockito-erstellten Mock verwenden und seine Felder festlegen könnten, würde dies die Kapselung brechen, und in jedem Fall würde es nicht einfach sein, private oder endgültige Felder zu setzen. Mit der aktuellen Spionagesyntax können Sie den Konstruktor Ihrer Wahl mit den Parametern Ihrer Wahl aufrufen und Ihre Klasse so genau wie möglich einrichten.
Aber warum nicht das alte Objekt behalten und delegieren? Die Antwort ist this
:
class AnotherThing {
String greet() {
return "Hello " + getName() + "!";
}
String getName() {
return "World";
}
}
class AnotherThingTest {
void testOverrideName() {
AnotherThing anotherThing = new AnotherThing();
AnotherThing spyOfAnotherThing = spy(anotherThing);
doReturn("Dolly").when(spyOfAnotherThing).getName();
assertEquals("Hello Dolly!", spyOfAnotherThing.greet()); // fails!
}
}
Die oben wie ein vernünftiger Test scheint, aber wenn Mockito auf Ihre AnotherThing Instanz delegieren, wäre es fehl: spyOfAnotherThing
würde delegieren anotherThing
, die getName
nennen würde (ausdrücklich this.getName()
) auf selbst, die den Standard "World" zurückgeben würde. Damit partielles Mocking funktionieren kann, muss der Wert this
zwischen der Spy-Implementierung und der ursprünglichen Implementierung identisch sein, und dies erfordert eine Kopie.
Aus diesem Grund sehen Sie oft spy(new ClassToSpy())
, wo der Entwickler keinen Verweis auf das ursprüngliche Objekt des Spions behält. Dies kann helfen, Verwirrung darüber zu vermeiden, mit welcher Instanz zu interagieren ist, und ich empfehle es sehr.
Danke für die Erklärung. Jetzt, da ich die gesamte Dokumentation gelesen habe, heißt es, dass das Objekt nur für die Felder verwendet wird – DariusL