Ich benutze Mockito in einigen Tests.
Ich habe folgende Klassen:
class BaseService {
public void save() {...}
}
public Childservice extends BaseService {
public void save(){
//some code
super.save();
}
}
Ich möchte nur den zweiten Aufruf ( super.save
) von verspotten ChildService
. Der erste Aufruf muss die reale Methode aufrufen. Gibt es eine Möglichkeit, das zu tun?
Antworten:
Nein, Mockito unterstützt dies nicht.
Dies ist möglicherweise nicht die Antwort, nach der Sie suchen, aber was Sie sehen, ist ein Symptom dafür, dass Sie das Designprinzip nicht anwenden:
Wenn Sie eine Strategie extrahieren, anstatt eine Superklasse zu erweitern, ist das Problem behoben.
Wenn Sie den Code jedoch nicht ändern dürfen, ihn aber trotzdem testen müssen, gibt es auf diese unangenehme Weise immer noch Hoffnung. Mit einigen AOP-Tools (zum Beispiel AspectJ) können Sie Code in die Super-Class-Methode einbinden und deren Ausführung vollständig vermeiden (yuck). Dies funktioniert nicht, wenn Sie Proxys verwenden. Sie müssen die Bytecode-Modifikation verwenden (entweder das Weben der Ladezeit oder das Weben der Kompilierungszeit). Es gibt spöttische Frameworks, die diese Art von Trick ebenfalls unterstützen, wie PowerMock und PowerMockito.
Ich schlage vor, Sie entscheiden sich für das Refactoring, aber wenn dies keine Option ist, werden Sie ernsthaften Hacking-Spaß haben.
quelle
//some codes
Code in eine Methode extrahieren, die separat getestet werden kann.Wenn Sie wirklich keine Wahl für das Refactoring haben, können Sie alles im Super-Methodenaufruf verspotten / stubben, z
quelle
BaseService
ist abstrakt, obwohl ich nicht sehe, warum das relevant wäre.super.validate()
Ziehen Sie in Betracht, den Code von der ChildService.save () -Methode in eine andere Methode umzugestalten und diese neue Methode zu testen, anstatt ChildService.save () zu testen. Auf diese Weise vermeiden Sie unnötigen Aufruf der Super-Methode.
Beispiel:
quelle
Erstellen Sie eine paketgeschützte Methode (setzt Testklasse in demselben Paket voraus) in der Unterklasse, die die Superklassenmethode aufruft, und rufen Sie diese Methode dann in Ihrer überschriebenen Unterklassenmethode auf. Sie können dann in Ihrem Test mithilfe des Spionagemusters Erwartungen an diese Methode setzen. Nicht schön, aber sicherlich besser, als sich mit allen Erwartungen an die Supermethode in Ihrem Test auseinandersetzen zu müssen
quelle
Auch wenn ich der Antwort von iwein voll und ganz zustimme (
), ich gebe zu, es gibt Zeiten, in denen Vererbung nur natürlich erscheint, und ich fühle mich nicht gebrochen oder umgestaltet, nur um einen Unit-Test durchzuführen.
Also mein Vorschlag:
Und dann im Unit-Test:
quelle
Der Grund dafür ist, dass Ihre Basisklasse nicht öffentlich ist. Mockito kann sie aufgrund der Sichtbarkeit nicht abfangen. Wenn Sie die Basisklasse als öffentlich oder @Override in der Unterklasse (als öffentlich) ändern, kann Mockito sie korrekt verspotten.
quelle
Wenn die Vererbung sinnvoll ist, ist es möglicherweise die einfachste Option, eine neue Methode (Paket privat ??) zu erstellen, um die Super-Methode aufzurufen (nennen wir sie superFindall), die reale Instanz auszuspionieren und dann die SuperFindAll () -Methode so zu verspotten, wie Sie es verspotten wollten die Elternklasse eins. Es ist nicht die perfekte Lösung in Bezug auf Abdeckung und Sichtbarkeit, aber es sollte den Job machen und es ist einfach anzuwenden.
quelle