Ich habe eine einfache Klasse, aber mit einem anonymen Code-Block. Ich muss diese Klasse mit Tests abdecken.
%Vor%Und testen:
%Vor%Kommentarzeile funktioniert nicht. Protokoll: Gesucht, aber nicht aufgerufen: dao.deleteAllByStatusAndDate ( , isA (java.util.Date)); - & gt; unter com.nxsystems.dw.publisher.handler.CleanerTaskTest.successfulScenario (CleanerTaskTest.java:52) Eigentlich gab es keine Interaktionen mit diesem Mock.
um com.nxsystems.dw.publisher.handler.CleanerTaskTest.successfulScenario (CleanerTaskTest.java:52) bei sun.reflect.NativeMethodAccessorImpl.invoke0 (Native Methode) um sun.reflect.NativeMethodAccessorImpl.invoke (NativeMethodAccessorImpl.java:39) beim sun.reflect.DelegatingMethodAccessorImpl.invoke (DelegatingMethodAccessorImpl.java:25) beim org.junit.runners.model.FrameworkMethod $ 1.runReflectiveCall (FrameworkMethod.java:44) beim org.junit.internal.runners.model.ReflectiveCallable.run (ReflectiveCallable.java:15) beim org.junit.runners.model.FrameworkMethod.invokeExplosively (FrameworkMethod.java:41) beim org.junit.internal.runners.statements.InvokeMethod.evaluate (InvokeMethod.java:20) beim org.junit.internal.runners.statements.RunBefores.evaluate (RunBefores.java:28) beim org.junit.runners.BlockJUnit4ClassRunner.runChild (BlockJUnit4ClassRunner.java:76) beim org.junit.runners.BlockJUnit4ClassRunner.runChild (BlockJUnit4ClassRunner.java:50) bei org.junit.runners.ParentRunner $ 3.run (ParentRunner.java:193) um org.junit.runners.ParentRunner $ 1.schedule (ParentRunner.java:52) um org.junit.runners.ParentRunner.runChildren (ParentRunner.java:191) um org.junit.runners.ParentRunner.access $ 000 (ParentRunner.java:42) um org.junit.runners.ParentRunner $ 2.evaluate (ParentRunner.java:184) um org.junit.runners.ParentRunner.run (ParentRunner.java:236) um org.mockito.internal.runners.JUnit45AndHigherRunnerImpl.run (JUnit45AndHigherRunnerImpl.java:37) beim org.mockito.runners.MockitoJUnitRunner.run (MockitoJUnitRunner.java:62) an org.junit.runner.JUnitCore.run (JUnitCore.java:157) um com.intellij.rt.execution.junit.JUnitStarter.main (JUnitStarter.java:62)
Auch wenn diese Tets gestartet werden, geht der Debugger nicht in den anonymen Block. Also, wie macht man Mockito in anonymen Block gehen?
Nun, Ihr Problem hier ist, dass TransactionTemplate in Ihrem Test ein Mock ist. Als solches hat es die gleiche Schnittstelle wie TransactionTemplate, aber es weiß nicht, wie es sich verhält. Sie sind verantwortlich für die Umsetzung - das ist der springende Punkt von Mocks. Sie rufen template.execute()
explizit in Ihrem Code auf und deshalb wird Ihre erste Überprüfung bestanden. Aber das execute()
ist nicht das von Spring (genauer gesagt ist template
in deinem Test keine Instanz von Spring's TransactionTemplate, es ist nur ein Mock davon) - es ist, na gut sagen Sie, es ist "leer", da es auf einem Schein aufgerufen wird und Sie haben dem Mock nicht gesagt, wie sich das Aufrufen von execute()
verhalten soll.
In solchen Fällen würde ich wirklich von solchen Unit-Tests abraten, weil Sie Implementierung hier testen. Was Sie testen sollten, zumindest für mich, ist die Funktionalität Bedeutung gegeben bestimmte Bedingungen, wenn etwas passiert dann Einige Ergebnisse sollten auftreten. Dies würde erfordern, dies zu einem Integrationstest zu ändern (unter Verwendung von beispielsweise DBUnit oder irgendetwas anderem) und festzustellen, ob Sie tatsächlich gelöscht haben, was Sie löschen sollten. Ich meine, was kümmert es dich wirklich - zu wissen, dass einige Methoden aufgerufen wurden oder dass etwas, auf das du gehofft hast, tatsächlich passiert ist?
Aber wenn Sie wirklich dieses anonyme Stück Code testen wollen, dann würde ich es einfach (die ganze anonyme Klasse) in eine separate Klasse extrahieren und einen Komponententest nur für diese neue Klasse schreiben und mehr Genau für die Methode doInTransaction()
. In diesem Fall würden Sie es mit new
erstellen, indem Sie einen Schein DataWarehouseMessageDao
setzen und einfach Ihre verify()
.
Sie sollten Ihren Code nicht ändern, es ist richtig. In Ihrem Komponententest sollten Sie anstelle von isA check ArgumentCaptor verwenden, um übergebene Parameter zu erfassen, diese Instanz als transactionCallback-Typ zu validieren und die Methode doInTransaction darauf aufzurufen. So könnten Sie überprüfen, ob dao mit dem erwarteten Parameter aufgerufen wurde (Sie könnten eq Matcher verwenden, um den genauen Wert zu überprüfen).
Es stimmt, dass du in diesem Test zwei Dinge gleichzeitig testest, aber es ist nur wegen deiner Implementierung und ich sage nicht, dass es falsch ist. Das Erstellen neuer Instanzen mit einer gewissen Geschäftslogik erhöht zwar die Kopplung in Ihrem Code, aber das bedeutet nicht, dass wir keine Sprachfähigkeiten dafür verwenden sollten.