为什么Java stacktrace只返回finally块中的失败?(Why Java stacktrace only returns failure in finally block?)

我写了一些自动化测试,我使用的语法如下 -

try { // Test case steps and validations } finally { // Clean up related to test }

注意:这没有catch块,因为我的测试不期望异常。

如果测试在try和finally块中都失败了,那么只有finally失败会在控制台上返回,而不是try 。 这里有一个简单的例子(TestNG用于断言) -

try { Assert.assertEquals(true, false, "Boolean values did not match"); } finally { Assert.assertEquals(100, 10, "Integer values did not match"); }

在这种情况下,只返回最终失败的细节。

这无助于确定在控制台上进行测试的实际失败。

我想了解为什么Java不会在控制台上返回两个故障细节,这可以帮助用户在第一眼看到故障原因。

I've written some automation tests where I use syntax like -

try { // Test case steps and validations } finally { // Clean up related to test }

NOTE: This does not have catch block as my tests do not expect exceptions.

If test fails in try as well as finally block, only failures of finally are returned on console but not of try. Simple example here(TestNG is used here for assertions) -

try { Assert.assertEquals(true, false, "Boolean values did not match"); } finally { Assert.assertEquals(100, 10, "Integer values did not match"); }

In this case, only details of finally failures are returned.

This does not help to identify actual failure of test looking at the console.

I would like to understand why Java does not return both failure details on console which can help user to identify failure cause at very first look.

最满意答案

抛出异常可以观察到同样的情况:

try { throw new RuntimeException("Message 1"); } finally { throw new RuntimeException("Message 2"); }

这里只打印Message 2 :

Exception in thread "main" java.lang.RuntimeException: Message 2

这是因为当finally抛出一个异常时, try任何异常都会被“丢弃并忘记”:

JLS第14.20.2节

如果V的运行时类型不是与try语句的任何catch子句的可捕获异常类分配兼容的,则执行finally块。 然后有一个选择:

如果finally块正常完成,那么try语句突然完成,因为抛出了值V.

如果因为S原因finally块突然完成,那么try语句因S原因突然完成( 并丢弃并丢弃值V的抛出 )。

The same thing can be observed with throwing exceptions:

try { throw new RuntimeException("Message 1"); } finally { throw new RuntimeException("Message 2"); }

Here, only Message 2 is printed:

Exception in thread "main" java.lang.RuntimeException: Message 2

This is because when finally throws an exception, any exceptions in try is "discarded and forgotten":

JLS section 14.20.2

If the run-time type of V is not assignment compatible with a catchable exception class of any catch clause of the try statement, then the finally block is executed. Then there is a choice:

If the finally block completes normally, then the try statement completes abruptly because of a throw of the value V.

If the finally block completes abruptly for reason S, then the try statement completes abruptly for reason S (and the throw of value V is discarded and forgotten).

更多推荐