2016-05-28 17 views
2

Ich habe einen Test mit spy Debugging und fand etwas sehr verwirrend.Was ist der Punkt einer ausspionierten Instanz

Ich erwartete Spion auf die übergebene Instanz zu verschieben.

testSpy1 schlägt fehl und testSpy2 gelingt, weil ich versuchte, Daten aus dem tatsächlichen Objekt anstelle des Spions zu lesen. Also, wenn Spion nicht mit dem übergebenen Objekt interagiert, warum akzeptiert es eins und warum hält es es in den Scheineinstellungen?

Antwort

3

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.

+1

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

Verwandte Themen