Mark Peters hat es sehr gut gemacht, die Ursache zu diagnostizieren und zu erklären. Ich kann mir ein paar Problemumgehungen vorstellen:
Verschieben Sie die (Neu-) Initialisierung des Caches in eine separate Methode.
Durch Aufruf von new CacheLoader
aus dem Spion wird die anonyme innere Klasse mit einem Verweis auf den Spion als Elterninstanz erstellt. Je nachdem, welches System Sie gerade testen, können Sie auch davon profitieren, dass die Cache-Erstellung außerhalb des Konstruktorpfads ausgeführt wird, insbesondere wenn eine umfangreiche Initialisierung oder ein Ladevorgang erforderlich ist.
Manuelle Überschreibung durchführen.
Die Ursache Ihres Problems liegt darin, dass sich die Spy-Instanz von der ursprünglichen Instanz unterscheidet. Indem Sie eine einzelne Instanz in Ihrem Test überschreiben, können Sie das Verhalten ändern, ohne sich mit der Nichtübereinstimmung zu befassen.
%Vor%Refactor.
Obwohl Sie sich für eine vollständige DI entscheiden können, können Sie vielleicht einfach eine Test-Naht zur Wertfunktion hinzufügen:
%Vor% Natürlich kann valueRetriever
abhängig von Ihren Bedürfnissen eine völlig separate Klasse sein, oder Sie könnten eine ganze CacheLoader
als Parameter akzeptieren.
Das kommt auf die Implementierung des Spions an. Laut den Dokumenten wird der Spy als erstellt kopiere von der realen Instanz:
Mockito delegiert keine Aufrufe an die übergebene reale Instanz, sondern erstellt stattdessen eine Kopie davon. Wenn Sie also die reale Instanz behalten und damit interagieren, erwarten Sie nicht, dass der Spion diese Interaktion und deren Auswirkungen auf den realen Zustand der Instanz bemerkt. Die logische Konsequenz ist, dass wenn eine unstubbed Methode auf dem Spion aufgerufen wird, aber nicht auf der realen Instanz , Sie keine Auswirkungen auf die reale Instanz.
Es scheint eine flache Kopie zu sein. Als Ergebnis zeigt mein Debugging, dass das CacheLoader
zwischen der Kopie und dem ursprünglichen Objekt geteilt wird, aber sein Verweis auf sein umschließendes Objekt ist das ursprüngliche Objekt, nicht der Spion. Daher wird der reelle retrieveValue
anstelle des verspotteten aufgerufen.
Ich bin mir nicht sicher, was der beste Weg wäre, dies zu lösen. Eine Möglichkeit für dieses spezielle Beispiel wäre, die CacheLoader
Abhängigkeit zu invertieren (d. H. Sie in Subject
anstelle von Subject
intern zu definieren) und diese anstelle von Subject
vorzutäuschen.