【问题标题】:Exceptions thrown while soft asserting fail the subsequent tests软断言时抛出的异常使后续测试失败
【发布时间】:2017-10-11 06:50:53
【问题描述】:

根据标题,我正在尝试循环运行测试用例。为了能够计算失败断言的数量,我期望如果 AssertJ 试图断言来自方法调用的返回值,它应该 失败一次迭代并继续。否则,它违背了软断言的目的。这是一个说明这一点的 sn-p:

    public static void main(String[] args) {
        SoftAssertions softAssertions = new SoftAssertions();
        softAssertions.assertThat(throwException(10)).isTrue();
        softAssertions.assertThat(throwException(10)).isTrue();
        softAssertions.assertThat(throwException(1)).isTrue();
        softAssertions.assertAll();
    }

    private static boolean throwException(int stuff){
        if(stuff == 1){
           throw new RuntimeException();
       }
       return true;
    }

输出:

   Exception in thread "main" java.lang.RuntimeException
    at eLCMUpdate.throwException(MyClass.java:101)
    at eLCMUpdate.main(MyClass.java:95)

我在这里遗漏了一些东西。我做错了吗?

【问题讨论】:

    标签: testing assertj


    【解决方案1】:

    代码softAssertions.assertThat(throwException(10)).isTrue();中的问题是,如果抛出异常,那么assertThat根本不会被执行。

    你需要懒惰地评估你在assertThat中传递的代码,你可以使用AssertJ assertThatCode来做到这一点,如下所示:

    final SoftAssertions softAssertions = new SoftAssertions();
    softAssertions.assertThatCode(() -> throwException(10)).doesNotThrowAnyException();
    softAssertions.assertThatCode(() -> throwException(1)).isInstanceOf(RuntimeException.class);
    softAssertions.assertAll();
    

    【讨论】:

    • 我见过这个选项,但问题是,我无法预测我可能遇到的所有异常。因为如果我没有一个狂野的 NPE,我的测试可能会失败。
    • 尽管如此 +1 assertThatCode 的想法。
    【解决方案2】:

    据我了解,软断言适用于布尔值,而不适用于异常。

    另外:如果你在调用softAssertions.assertAll()之前抛出异常,显然这个方法也永远不会被执行。这实际上是您报告的行为的原因。

    只需尝试调试您的代码,您就会发现softAssertions.assertAll() 从未被调用过。

    如果您将代码更改为,软断言将正常工作:

    @Test
    void soft_assertions() {
        SoftAssertions softAssertions = new SoftAssertions();
        softAssertions.assertThat(checkCondition(10)).isTrue();
        softAssertions.assertThat(checkCondition(10)).isTrue();
        softAssertions.assertThat(checkCondition(1)).isTrue();
        softAssertions.assertThat(checkCondition(2)).isTrue();
        softAssertions.assertThat(checkCondition(20)).isTrue();
        softAssertions.assertAll();
    }
    
    private static boolean checkCondition(int stuff){
        if(stuff == 1 || stuff == 2){
            return false;
        }
        return true;
    }
    

    这将输出多个断言的结果,并且不会在评估第一个失败的断言时停止。

    输出:

    org.assertj.core.api.SoftAssertionError: 
    The following 2 assertions failed:
    1) 
    Expecting:
     <false>
    to be equal to:
     <true>
    but was not.
    at JsonStewardshipCustomerConversionTest.soft_assertions(JsonStewardshipCustomerConversionTest.java:301)
    2) 
    Expecting:
     <false>
    to be equal to:
     <true>
    but was not.
    at JsonStewardshipCustomerConversionTest.soft_assertions(JsonStewardshipCustomerConversionTest.java:302)
    

    更新

    SoftAssertion 似乎不符合您的目的。

    我建议您改用 JUnit 5 assertAll。根据我的测试,它会评估 assertAll 块中的所有条件并在异常中幸存下来。这里的问题是你需要 JUnit 5,它可能还没有被广泛采用。

    这是一个布尔条件失败的示例,也是一个异常。两者都在控制台中报告。

    @Test
    void soft_assertions() {
        assertAll("Check condition",
                () -> assertThat(checkCondition(9)).isTrue(),
                () -> assertThat(checkCondition(10)).isTrue(),
                () -> assertThat(checkCondition(11)).isTrue(),
                () -> assertThat(checkCondition(2)).isTrue(), // Throws exception
                () -> assertThat(checkCondition(3)).isFalse(), // fails
                () -> assertThrows(IllegalArgumentException.class, () -> {
                    checkCondition(1);
                })
        );
    }
    
    private static boolean checkCondition(int stuff) {
        if (stuff == 1 || stuff == 2) {
            throw new IllegalArgumentException();
        }
        return true;
    }
    

    你会在输出中看到这个:

    org.opentest4j.MultipleFailuresError: Check condition (2 failures)
        <no message> in java.lang.IllegalArgumentException
    
    Expecting:
     <true>
    to be equal to:
     <false>
    but was not.
    

    【讨论】:

    • 这只是为了测试 AssertJ 如何处理异常。我的实际代码有一个方法调用,这个方法容易被抛出异常。我总是可以捕获异常并处理它们,但这对我来说似乎不合逻辑,而且正如我所说的那样违背了软断言的目的。
    • 非常感谢您提供的信息。出于某种原因,我似乎无法获得您得到的输出:/ 您使用的是哪个 assertThat 函数?在我看来,来自 AssertJ 的那个。
    • 查看assertAll 上的 JUnit 5 指南示例。见junit.org/junit5/docs/current/user-guideassertAll 可以帮助您,因为它会根据您的需要处理异常。
    • 如果您的回答是正确的,我很乐意接受。我只是无法得到你得到的输出。你能帮我指出我做错了什么吗?
    • @enissay,我创建了一个 GitHub 存储库 maven 项目,其中包含此测试的代码,您可以克隆并试用:github.com/gilfernandes/junit5test。也请不要说我没有发布完整的测试输出,但我错过了它的某些部分。但相关信息确实在帖子里。
    猜你喜欢
    • 1970-01-01
    • 2020-03-11
    • 2015-12-18
    • 1970-01-01
    • 2011-06-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多