ich den folgenden Code haben initialisiert werden:Mockito Spion ist fehlgeschlagen, da Klassenmitglied kann nicht
public class MyClass() {
private MyObject myObject = getMyObject();
public MyObject getMyObject() {
if (myObject == null) {
myObject = MyStaticClass.createMyObject();
}
return myObject;
}
// heaps more methods
}
public class MyTest() {
private MyClass spyMyClass = spy(new MyClass());
public MyTest() {
doReturn(null).when(spyMyClass).getMyObject();
}
@Test
public void someTest() {
ClassUnderTest c = new ClassUnderTest();
assertTrue(c.someMethod(spyMyClass));
}
}
Der Test mit einem Fehler gescheitert Could not initialise class MyStaticClass
. Der Grund dafür ist, dass diese statische Klasse viele weitere Klassenobjekte initialisiert, die während des Tests nicht verfügbar sind (z. B. Datenbank), und es ist mir egal, wie Sie sehen können. Ich bin in Ordnung, wenn die Methode getMyObject()
aufgerufen wird.
Aber das scheiterte Absicht als auch, weil vor der doReturn(null)
Linie erreicht ist, hat der Test bereits in der spy(new MyClass())
Linie gescheitert, in dem es getMyObject()
das private Mitglied myObject
zu initialisieren nennt.
Eine Abhilfe auf die oben beschriebene Situation ist mock(MyClass.class)
statt spy(new MyClass())
, zu verwenden, so dass der private Mitglied myObject
ist nicht initialisiert werden und somit nicht die reale getMyObject()
Methode aufrufen.
Aber diese Problemumgehung erzeugt einen weiteren Kopfschmerz für mich, denn das bedeutet, dass ich einige Konfiguration vornehmen muss (sogar nur doCallRealMethod()
) für diese Haufen mehr Methoden innerhalb MyClass
.
Frage: Gibt es eine andere Lösung, die ich immer noch Spion auf einer Instanz von MyClass
verwenden kann, so dass ich diese Heaps mehr Methoden innerhalb dieser Klasse konfigurieren kann, aber ich kann um den Could not initialise class MyStaticClass
Fehler umgehen?
P.S. Ich kann nicht einfach Power Mock verwenden, um MyStaticClass
zu verspotten, weil ich bereits einen anderen Test-Runner für MyTest
verwende. Es sei denn, Ihre Antwort kann zeigen, wie einfach es ist, zwei Testläufer gleichzeitig zu fahren, ohne einen neuen Hybrid-Testläufer zu implementieren, der beides kombiniert.
Dank Adam, jetzt habe ich ein gutes Arbeits Code haben:
public class MyTest() {
private MyClass spyMyClass = spy(new MyClass() {
@Override
public MyObject getMyObject() {
return null;
}
});
@Test
public void someTest() {
ClassUnderTest c = new ClassUnderTest();
assertTrue(c.someMethod(spyMyClass));
}
}
Danke, es sieht gut aus. Ist es Standard beim Komponententest? 'MyClass' ist eine Util-Klasse. Nicht viel tun, aber hat viele Varianten der gleichen Funktionen (z. B. Varianten von 1 oder 2 oder 3 Parameter), so dass ich nur widerwillig bin, alle von ihnen zu verspotten. – user1589188
Man könnte argumentieren, dass Multi-Parameter-Schnittstelle Bloat das Problem erhöhen kann. Aber ohne die Quelle zu sehen, ist es schwer, explizit zu antworten. Ich würde die andere Frage stellen - macht 'MyClass' viele Dinge: z.B. geben Sie Datenbankkonfiguration + Serverkonfiguration geben + Anwendungskonfiguration geben? Wenn dies der Fall ist, könnte es in drei separate Einheiten aufgeteilt werden, die nur über Schnittstellen sichtbar sind. Dann sollten sie leichter zu verspotten sein. –