【问题标题】:Why Java stacktrace only returns failure in finally block?为什么 Java stacktrace 只在 finally 块中返回失败?
【发布时间】:2018-03-20 22:23:46
【问题描述】:

我已经编写了一些自动化测试,其中使用了类似的语法 -

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

注意:这没有 catch 块,因为我的测试不会出现异常。

如果测试在tryfinally 块中失败,则控制台上仅返回finally 的失败,而不是try。这里的简单例子(TestNG 在这里用于断言)-

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

在这种情况下,只返回 finally 失败的详细信息。

这无助于通过控制台识别测试的实际失败。

我想了解为什么 Java 不会在控制台上返回这两个故障详细信息,这可以帮助用户在第一时间识别故障原因。

【问题讨论】:

  • 我会调查你的测试框架设置/拆除测试的能力,而不是在你的测试中手动设置和拆除(就像你做的那样)

标签: java


【解决方案1】:

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

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 值而突然完成。

    • 如果 finally 块由于原因 S 突然完成,则 try 语句由于原因 S (和 value 的抛出 V 被丢弃和遗忘)。

【讨论】:

    【解决方案2】:

    因为在后台Assert.assertEquals() 使用Assert.fail() 抛出AssertionError 来表示错误。

    finally 块中的异常将按照14.20.2. Execution of try-finally and try-catch-finally 替换并丢弃try 块中抛出的异常。

    【讨论】:

    • 它没有更高的优先级。如果 finally 块在处理异常时抛出异常,它会替换异常,或者正如 JLS 所称:原始异常是“丢弃和遗忘”。
    【解决方案3】:

    这是因为从 finally 块抛出的新异常替换try 块抛出的异常,如 Java 语言规范,14.20.2. Execution of try-finally and try-catch-finally 部分所述:

    如果try 块的执行由于throw 的值V 而突然完成,那么有一个选择:

    [...]

    如果finally 块由于原因S 而突然完成,那么try 语句由于原因S 而突然完成(并且价值Vthrow 被丢弃和遗忘强>)。

    由于finally 块甚至不知道最初的异常,它无法对此做任何事情。

    但是,如果您 catch 原始异常,则可以将其作为已抑制 异常(Java 7+)包含在内,但这有点令人费解:

    AssertionError originalError = null;
    try {
        Assert.assertEquals(true, false, "Boolean values did not match");
    } catch (AssertionError e) {
        originalError = e;
        throw e;
    } finally {
        try {
            Assert.assertEquals(100, 10, "Integer values did not match");
        } catch (AssertionError e) {
            if (originalError == null)
                throw e;
            originalError.addSuppressed(e);
            throw originalError;
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2010-09-08
      • 1970-01-01
      • 2018-12-28
      • 2013-04-08
      • 2012-08-12
      相关资源
      最近更新 更多