1. 概述

在编写单元测试时,我们有时会对输出进行多条断言。一旦第一条断言失败,测试就会停止,这意味着我们无法得知后续断言的结果,这可能会增加调试时间。

为了解决这个问题,我们可以将多个断言组合成一个操作。

在这个简短的教程中,我们将学习如何使用JUnit5引入的assertAll()方法,并了解它与使用多个独立断言有何不同。

2. 模型

我们将使用一个User类来举例说明:

public class User {
    String username;
    String email;
    boolean activated;
    //constructors
   //getters and setters
}

3. 使用多个断言

让我们从所有断言都会失败的例子开始:

User user = new User("baeldung", "[email protected]", false);
assertEquals("admin", user.getUsername(), "Username should be admin");
assertEquals("[email protected]", user.getEmail(), "Email should be [email protected]");
assertTrue(user.getActivated(), "User should be activated");

运行测试后,只会显示第一条断言的失败:

org.opentest4j.AssertionFailedError: Username should be admin ==> 
Expected :admin
Actual   :baeldung

假设我们修复了失败的代码或测试并重新运行,那么会得到第二个失败,依此类推。在这种情况下,将这些断言组合成单个通过/失败情况会更好。

4. 使用assertAll()方法

我们可以使用JUnit5的assertAll()方法来分组断言。

4.1. assertAll()的理解

assertAll()断言函数接受一个包含多个Executable对象的集合:

assertAll(
  "Grouped Assertions of User",
  () -> assertEquals("baeldung", user.getUsername(), "Username should be baeldung"),
  // more assertions
  ...
 );

因此,我们可以使用lambda表达式提供每个断言。lambda将在assertAll()提供的分组内执行断言。

在这里,在assertAll()的第一个参数中,我们也提供了描述,以解释整个组的意义。

4.2. 使用assertAll()分组断言

让我们看看完整的例子:

User user = new User("baeldung", "[email protected]", false);
assertAll(
  "Grouped Assertions of User",
  () -> assertEquals("admin", user.getUsername(), "Username should be admin"),
  () -> assertEquals("[email protected]", user.getEmail(), "Email should be [email protected]"),
  () -> assertTrue(user.getActivated(), "User should be activated")
);

现在,我们来看看当运行测试时会发生什么:

org.opentest4j.MultipleFailuresError: Grouped Assertions of User (3 failures)
org.opentest4j.AssertionFailedError: Username should be admin ==> expected: <admin> but was: <baeldung>
org.opentest4j.AssertionFailedError: Email should be [email protected] ==> expected: <[email protected]> but was: <[email protected]>
org.opentest4j.AssertionFailedError: User should be activated ==> expected: <true> but was: <false>

与使用多个独立断言的情况相反,这次所有断言都被执行,并且它们的失败信息都包含在MultipleFailuresError消息中。

需要注意的是,assertAll()仅处理AssertionError如果任何断言以异常结束,而不是通常的AssertionError,则立即停止执行,并将错误输出与异常相关,而不是MultipleFailuresError

5. 总结

在这篇文章中,我们学会了在JUnit5中使用assertAll(),并了解了它与使用多个单独断言的区别。

如往常一样,本教程的完整代码可以在GitHub上找到:GitHub链接