我一直在 Eclipse 中使用 JUnit 创建单元测试,并且 JUnit 的基本原理对我来说很清楚。测试按应有的方式运行,现在是时候找到一种报告失败测试的好方法了。我在网上遇到的大多数示例都是使用某种构建系统(如 Ant、Maven 或 Hudson)在构建项目的同时运行测试,但在构建过程中不需要这种集成。测试应该能够独立于构建系统运行。最后,这些系统只是获取从 JUnit 获得的信息,并将其放入一个漂亮的 HTML 布局中。
我了解到,可以通过 JUnitCore 的 RunListener 类创建自定义侦听器来读取 JUnit 信息,并使用“testFailure”方法处理发生的故障。创建测试时,我总是为断言错误提供自定义消息。我的问题是这条消息没有出现在 JUnit 的失败跟踪中。相反,失败跟踪将显示“java.lang.Exception:无法调用 *”。当我查看控制台时,我看到了相同的堆栈跟踪,但下面还有一行前面是“Caused by: *”,在这里我确实看到了我的自定义错误消息。
Caused by: java.lang.AssertionError: <my custom error message>
at *
由于我刚刚开始使用 JUnit,我不知道这是否是 JUnit 的正常行为,还是我实现测试的方式有问题,我是否应该在故障跟踪中看到我的自定义消息?我还注意到,当我在执行测试的方法中发现断言错误时,我可以使用“error.getMessage()”访问该消息。因此,如果有必要,这将是一个解决方案,并且还允许我在报告中包含在我发现错误时可访问的附加信息(即网页的 url 等),但在每个断言周围放置一个 try-catch 块在我看来,这会破坏它的目的。
正如我所说,我是单元测试的新手,也是一般的 java 开发新手,所以我很可能会犯一些愚蠢的错误。非常欢迎任何指针!
更新 2:在控制台上的堆栈跟踪 的匿名版本下方。也许这有助于澄清我的问题。
java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.lang.reflect.Method.invoke(Unknown Source)
at xxxxx.xxxxxxxxxxxx.xxxxxxxxx(xxxxxxxxxxx.java:103)
at xxxxx.xxxxxxxxxxxxxx.xxxxxx(xxxxxxxxxxx.java:62)
at junit.framework.TestCase.runBare(TestCase.java:134)
at junit.framework.TestResult$1.protect(TestResult.java:110)
at junit.framework.TestResult.runProtected(TestResult.java:128)
at junit.framework.TestResult.run(TestResult.java:113)
at junit.framework.TestCase.run(TestCase.java:124)
at xxxxx.xxxxxxxxxxxx.xxxxx(xxxxxxxxxxxx.java:90)
at junit.framework.TestSuite.runTest(TestSuite.java:243)
at junit.framework.TestSuite.run(TestSuite.java:238)
at xxxxx.xxxxxxxxxxxxxxxxxxxx.xxxx(xxxxxxxxxxxxxxxx.java:87)
at junit.framework.TestSuite.runTest(TestSuite.java:243)
at junit.framework.TestSuite.run(TestSuite.java:238)
at xxxxx.xxxxxxxxxxxxxxxxxxxxxx.xxxxx(xxxxxxxxxxxxxx.java:87)
at junit.framework.TestSuite.runTest(TestSuite.java:243)
at junit.framework.TestSuite.run(TestSuite.java:238)
at org.junit.internal.runners.JUnit38ClassRunner.run(JUnit38ClassRunner.java:83)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197)
Caused by: java.lang.AssertionError: <xx my custom message xx>.
at xxx.xxxxxxxx.xxxxxxxxxxxxxx(xxxxxxxx.java:100)
... 27 more
下面是 JUnit java.lang.Exception: could not invoke action on current page报告的堆栈跟踪的匿名版本
java.lang.Exception: could not invoke action <xx action name xxx> on current page class xxxx.xxxxxxx: [Ljava.lang.StackTraceElement;@71d382ab
at xxxxx.xxxxxxxxxxxxxxxxx.xxxxx(xxxxxxxxxxxxxxxxxxxx.java:65)
at junit.framework.TestCase.runBare(TestCase.java:134)
at junit.framework.TestResult$1.protect(TestResult.java:110)
at junit.framework.TestResult.runProtected(TestResult.java:128)
at junit.framework.TestResult.run(TestResult.java:113)
at junit.framework.TestCase.run(TestCase.java:124)
at xxxxx.xxxxxxxxxxxxxxxxx.xxxxx(xxxxxxxxxxxxxxxxxxxx.java:90)
at junit.framework.TestSuite.runTest(TestSuite.java:243)
at junit.framework.TestSuite.run(TestSuite.java:238)
at xxxxx.xxxxxxxxxxxxxxxxx.xxxxx(xxxxxxxxxxxxxxxxxxxx.java:87)
at junit.framework.TestSuite.runTest(TestSuite.java:243)
at junit.framework.TestSuite.run(TestSuite.java:238)
at xxxxx.xxxxxxxxxxxxxxxxx.xxxxx(xxxxxxxxxxxxxxxxxxxx.java:87)
at junit.framework.TestSuite.runTest(TestSuite.java:243)
at junit.framework.TestSuite.run(TestSuite.java:238)
at org.junit.internal.runners.JUnit38ClassRunner.run(JUnit38ClassRunner.java:83)
at org.junit.runners.Suite.runChild(Suite.java:128)
at org.junit.runners.Suite.runChild(Suite.java:24)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222)
at org.junit.runners.ParentRunner.run(ParentRunner.java:300)
at org.junit.runner.JUnitCore.run(JUnitCore.java:157)
at org.junit.runner.JUnitCore.run(JUnitCore.java:136)
at org.junit.runner.JUnitCore.run(JUnitCore.java:117)
at xxxxx.<xx class that initiates the RunListener xx>.main(<xx class that initiates the RunListener xx>.java:11)