Assertions in JUnit 4 and JUnit 5 – JUnit 4和JUnit 5中的断言

最后修改: 2018年 3月 15日

中文/混合/英文(键盘快捷键:t)

1. Introduction

1.介绍

In this article, we’re going to explore in details the assertions available within JUnit.

在这篇文章中,我们将详细探讨JUnit中可用的断言。

Following the migrating from JUnit 4 to JUnit 5 and A Guide to JUnit 5 articles, we’re now going into details about the different assertions available in JUnit 4 and JUnit 5.

从JUnit 4迁移到JUnit 5JUnit 5指南文章之后,我们现在将详细介绍JUnit 4和JUnit 5中可用的不同断言。

We’ll also highlight the enhancements made on the assertions with JUnit 5.

我们还将强调JUnit 5对断言的增强。

2. Assertions

2.断言

Assertions are utility methods to support asserting conditions in tests; these methods are accessible through the Assert class, in JUnit 4, and the Assertions one, in JUnit 5.

断言是支持测试中断言条件的实用方法;这些方法可以通过JUnit 4中的Assert 类和JUnit 5中的Assertions 一来访问。

In order to increase the readability of the test and of the assertions itself, it’s always recommended to import statically the respective class. In this way, we can refer directly to the assertion method itself without the representing class as a prefix.

为了提高测试和断言本身的可读性,我们总是建议静态地导入各自的类。通过这种方式,我们可以直接引用断言方法本身,而无需将代表类作为前缀。

Let’s start exploring the assertions available with JUnit 4.

让我们开始探索JUnit 4的可用断言。

3. Assertions in JUnit 4

3.JUnit 4中的断言

In this version of the library, assertions are available for all primitive types, Objects, and arrays (either of primitives or Objects).

在这个版本的库中,断言对所有原始类型、对象数组(无论是原始类型还是对象)都可用。

The parameters order, within the assertion, is the expected value followed by the actual value; optionally the first parameter can be a String message that represents the message output of the evaluated condition.

在断言中,参数的顺序是预期值,然后是实际值;可以选择第一个参数是一个String消息,代表被评估条件的消息输出。

There’s only one slightly different in how is defined the assertThat assertions, but we’ll cover it later on.

在如何定义assertThat断言方面只有一点不同,但我们将在后面介绍。

Let’s start with the assertEquals one.

让我们从assertEquals这个开始。

3.1. assertEquals

3.1.assertEquals

The assertEquals assertion verifies that the expected and the actual values are equal:

assertEquals断言验证了预期值和实际值是否相等。

@Test
public void whenAssertingEquality_thenEqual() {
    String expected = "Baeldung";
    String actual = "Baeldung";

    assertEquals(expected, actual);
}

It’s also possible to specify a message to display when the assertion fails:

也可以指定当断言失败时要显示的信息。

assertEquals("failure - strings are not equal", expected, actual);

3.2. assertArrayEquals

3.2.assertArrayEquals

If we want to assert that two arrays are equals, we can use the assertArrayEquals:

如果我们想断言两个数组是相等的,我们可以使用assertArrayEquals:

@Test
public void whenAssertingArraysEquality_thenEqual() {
    char[] expected = {'J','u','n','i','t'};
    char[] actual = "Junit".toCharArray();
    
    assertArrayEquals(expected, actual);
}

If both arrays are null, the assertion will consider them equal:

如果两个数组都是null,断言将认为它们相等。

@Test
public void givenNullArrays_whenAssertingArraysEquality_thenEqual() {
    int[] expected = null;
    int[] actual = null;

    assertArrayEquals(expected, actual);
}

3.3. assertNotNull and assertNull

3.3.assertNotNullassertNull

When we want to test if an object is null we can use the assertNull assertion:

当我们想测试一个对象是否为null时,我们可以使用assertNull断言。

@Test
public void whenAssertingNull_thenTrue() {
    Object car = null;
    
    assertNull("The car should be null", car);
}

In the opposite way, if we want to assert that an object should not be null we can use the assertNotNull assertion.

反过来说,如果我们想断言一个对象不应该是空的,我们可以使用assertNotNull断言

3.4. assertNotSame and assertSame

3.4. assertNotSameassertSame

With assertNotSame, it’s possible to verify if two variables don’t refer to the same object:

通过assertNotSame,我们可以验证两个变量是否指代同一个对象。

@Test
public void whenAssertingNotSameObject_thenDifferent() {
    Object cat = new Object();
    Object dog = new Object();

    assertNotSame(cat, dog);
}

Otherwise, when we want to verify that two variables refer to the same object, we can use the assertSame assertion.

否则,当我们想验证两个变量是否指向同一个对象时,我们可以使用assertSame断言。

3.5. assertTrue and assertFalse

3.5.assertTrueassertFalse

In case we want to verify that a certain condition is true or false, we can respectively use the assertTrue assertion or the assertFalse one:

如果我们想验证某个条件是truefalse,我们可以分别使用assertTrue断言或assertFalse断言。

@Test
public void whenAssertingConditions_thenVerified() {
    assertTrue("5 is greater then 4", 5 > 4);
    assertFalse("5 is not greater then 6", 5 > 6);
}

3.6. fail

3.6.失败

The fail assertion fails a test throwing an AssertionFailedError. It can be used to verify that an actual exception is thrown or when we want to make a test failing during its development.

fail断言使测试失败,抛出一个AssertionFailedError。它可以用来验证是否抛出了一个实际的异常,或者当我们想在测试的开发过程中使其失败。

Let’s see how we can use it in the first scenario:

让我们看看如何在第一种情况下使用它。

@Test
public void whenCheckingExceptionMessage_thenEqual() {
    try {
        methodThatShouldThrowException();
        fail("Exception not thrown");
    } catch (UnsupportedOperationException e) {
        assertEquals("Operation Not Supported", e.getMessage());
    }
}

3.7. assertThat

3.7.assertThat

The assertThat assertion is the only one in JUnit 4 that has a reverse order of the parameters compared to the other assertions.

assertThat断言是JUnit 4中唯一一个与其他断言相比具有反向参数顺序的断言。

In this case, the assertion has an optional failure message, the actual value, and a Matcher object.

在这种情况下,断言有一个可选的失败信息、实际值和一个Matcher对象。

Let’s see how we can use this assertion to check if an array contains particular values:

让我们看看我们如何使用这个断言来检查一个数组是否包含特定的值。

@Test
public void testAssertThatHasItems() {
    assertThat(
      Arrays.asList("Java", "Kotlin", "Scala"), 
      hasItems("Java", "Kotlin"));
}

Additional information, on the powerful use of the assertThat assertion with Matcher object, is available at Testing with Hamcrest.

有关使用assertThat断言与Matcher对象的强大功能的其他信息,可在使用Hamcrest进行测试

4. JUnit 5 Assertions

4.JUnit 5断言

JUnit 5 kept many of the assertion methods of JUnit 4 while adding few new ones that take advantage of the Java 8 support.

JUnit 5保留了JUnit 4的许多断言方法,同时增加了一些利用Java 8支持的新方法。

Also in this version of the library, assertions are available for all primitive types, Objects, and arrays (either of primitives or Objects).

在这个版本的库中,断言也可用于所有原始类型、对象和数组(原始类型或对象)。

The order of the parameters of the assertions changed, moving the output message parameter as the last parameter. Thanks to the support of Java 8, the output message can be a Supplier, allowing lazy evaluation of it.

断言的参数顺序发生了变化,输出消息参数被移到了最后一个参数。由于Java 8的支持,输出消息可以是一个Supplier,允许对其进行懒惰评估。

Let’s start reviewing the assertions that already had a JUnit 4 equivalent.

让我们开始回顾那些已经有JUnit 4等价物的断言。

4.1. assertArrayEquals

4.1.assertArrayEquals

The assertArrayEquals assertion verifies that the expected and the actual arrays are equals:

assertArrayEquals 断言验证了预期数组和实际数组是相等的。

@Test
public void whenAssertingArraysEquality_thenEqual() {
    char[] expected = { 'J', 'u', 'p', 'i', 't', 'e', 'r' };
    char[] actual = "Jupiter".toCharArray();

    assertArrayEquals(expected, actual, "Arrays should be equal");
}

If the arrays aren’t equal, the message “Arrays should be equal” will be displayed as output.

如果数组不相等,将显示”数组应该相等“的信息作为输出。

4.2. assertEquals

4.2.assertEquals

In case we want to assert that two floats are equals, we can use the simple assertEquals assertion:

如果我们想断言两个floats是相等的,我们可以使用简单的assertEquals断言。

@Test
void whenAssertingEquality_thenEqual() {
    float square = 2 * 2;
    float rectangle = 2 * 2;

    assertEquals(square, rectangle);
}

However, if we want to assert that the actual value differs by a predefined delta from the expected value, we can still use the assertEquals but we have to pass the delta value as the third parameter:

然而,如果我们想断言实际值与预期值相差一个预定义的delta,我们仍然可以使用assertEquals,但我们必须将delta值作为第三个参数传递。

@Test
void whenAssertingEqualityWithDelta_thenEqual() {
    float square = 2 * 2;
    float rectangle = 3 * 2;
    float delta = 2;

    assertEquals(square, rectangle, delta);
}

4.3. assertTrue and assertFalse

4.3.assertTrueassertFalse

With the assertTrue assertion, it’s possible to verify the supplied conditions are true:

通过assertTrue断言,可以验证所提供的条件是

@Test
void whenAssertingConditions_thenVerified() {
    assertTrue(5 > 4, "5 is greater the 4");
    assertTrue(null == null, "null is equal to null");
}

Thanks to the support of the lambda expression, it’s possible to supply a BooleanSupplier to the assertion instead of a boolean condition.

由于lambda表达式的支持,我们可以为断言提供一个BooleanSupplier而不是一个boolean条件。

Let’s see how we can assert the correctness of a BooleanSupplier using the assertFalse assertion:

让我们看看如何使用assertFalse断言来断言BooleanSupplier的正确性。

@Test
public void givenBooleanSupplier_whenAssertingCondition_thenVerified() {
    BooleanSupplier condition = () -> 5 > 6;

    assertFalse(condition, "5 is not greater then 6");
}

4.4. assertNull and assertNotNull

4.4.assertNullassertNotNull

When we want to assert that an object is not null we can use the assertNotNull assertion:

当我们想断言一个对象不是null时,我们可以使用assertNotNull断言。

@Test
void whenAssertingNotNull_thenTrue() {
    Object dog = new Object();

    assertNotNull(dog, () -> "The dog should not be null");
}

In the opposite way, we can use the assertNull assertion to check if the actual is null:

相反,我们可以使用assertNull断言来检查实际是否为null

@Test
public void whenAssertingNull_thenTrue() {
    Object cat = null;

    assertNull(cat, () -> "The cat should be null");
}

In both cases, the failure message will be retrieved in a lazy way since it’s a Supplier.

在这两种情况下,由于是Supplier,失败信息将以一种懒惰的方式被检索。

4.5. assertSame and assertNotSame

4.5.assertSameassertNotSame

When we want to assert that the expected and the actual refer to the same Object, we must use the assertSame assertion:

当我们想断言预期的和实际的指的是同一个Object时,我们必须使用assertSame断言。

@Test
void whenAssertingSameObject_thenSuccessfull() {
    String language = "Java";
    Optional<String> optional = Optional.of(language);

    assertSame(language, optional.get());
}

In the opposite way, we can use the assertNotSame one.

以相反的方式,我们可以使用assertNotSame一个。

4.6. fail

4.6.失败

The fail assertion fails a test with the provided failure message as well as the underlying cause. This can be useful to mark a test when it’s development it’s not completed:

fail 断言使测试失败,并提供失败信息以及根本原因。这对于标记一个测试,当它的开发没有完成时,是很有用的。

@Test
public void whenFailingATest_thenFailed() {
    // Test not completed
    fail("FAIL - test not completed");
}

4.7. assertAll

4.7.assertAll

One of the new assertion introduced in JUnit 5 is assertAll.

JUnit 5中引入的一个新断言是assertAll

This assertion allows the creation of grouped assertions, where all the assertions are executed and their failures are reported together. In details, this assertion accepts a heading, that will be included in the message string for the MultipleFailureError, and a Stream of Executable.

这个断言允许创建分组断言,所有的断言被执行,它们的失败被一起报告。在细节上,这个断言接受一个标题,它将包括在MultipleFailureError的消息字符串中,以及StreamExecutable.

Let’s define a grouped assertion:

我们来定义一个分组的断言。

@Test
void givenMultipleAssertion_whenAssertingAll_thenOK() {
    Object obj = null;
    assertAll(
      "heading",
      () -> assertEquals(4, 2 * 2, "4 is 2 times 2"),
      () -> assertEquals("java", "JAVA".toLowerCase()),
      () -> assertNull(obj, "obj is null")
    );
}

The execution of a grouped assertion is interrupted only when one of the executables throws a blacklisted exception (OutOfMemoryError for example).

只有当其中一个可执行程序抛出黑名单上的异常(例如OutOfMemoryError)时,分组断言的执行才会中断。

4.8. assertIterableEquals

4.8.assertIterableEquals

The assertIterableEquals asserts that the expected and the actual iterables are deeply equal.

assertIterableEquals 断言预期的和实际的迭代器是深度相等的。

In order to be equal, both iterable must return equal elements in the same order and it isn’t required that the two iterables are of the same type in order to be equal.

为了相等,两个迭代器必须以相同的顺序返回相等的元素,而且并不要求两个迭代器是相同的类型,以便相等。

With this consideration, let’s see how we can assert that two lists of different types (LinkedList and ArrayList for example) are equal:

基于这样的考虑,让我们看看如何断言两个不同类型的列表(LinkedListArrayList为例)是相等的。

@Test
void givenTwoLists_whenAssertingIterables_thenEquals() {
    Iterable<String> al = new ArrayList<>(asList("Java", "Junit", "Test"));
    Iterable<String> ll = new LinkedList<>(asList("Java", "Junit", "Test"));

    assertIterableEquals(al, ll);
}

In the same way of the assertArrayEquals, if both iterables are null, they are considered equal.

assertArrayEquals的方式相同,如果两个iterables都是null,则认为它们相等。

4.9. assertLinesMatch

4.9.assertLinesMatch

The assertLinesMatch asserts that the expected list of String matches the actual list.

assertLinesMatch断言预期的String列表与实际的列表相符。

This method differs from the assertEquals and assertIterableEquals since, for each pair of expected and actual lines, it performs this algorithm:

这个方法与assertEqualsassertIterableEquals不同,因为对于每一对预期行和实际行,它都执行这个算法。

  1. check if the expected line is equal to the actual one. If yes it continues with the next pair
  2. treat the expected line as a regular expression and performs a check with the String.matches() method. If yes it continues with the next pair
  3. check if the expected line is a fast-forward marker. If yes apply fast-forward and repeat the algorithm from the step 1

Let’s see how we can use this assertion to assert that two lists of String have matching lines:

让我们看看我们如何使用这个断言来断言两个String的列表有匹配的行。

@Test
void whenAssertingEqualityListOfStrings_thenEqual() {
    List<String> expected = asList("Java", "\\d+", "JUnit");
    List<String> actual = asList("Java", "11", "JUnit");

    assertLinesMatch(expected, actual);
}

4.10. assertNotEquals

4.10.assertNotEquals

Complementary to the assertEquals, the assertNotEquals assertion asserts that the expected and the actual values aren’t equal:

作为对assertEquals的补充,assertNotEquals断言断言预期值和实际值并不相等。

@Test
void whenAssertingEquality_thenNotEqual() {
    Integer value = 5; // result of an algorithm
    
    assertNotEquals(0, value, "The result cannot be 0");
}

If both are null, the assertion fails.

如果两者都是null,则断言失败。

4.11. assertThrows

4.11.assertThrows

In order to increase simplicity and readability, the new assertThrows assertion allows us a clear and a simple way to assert if an executable throws the specified exception type.

为了提高简单性和可读性,新的assertThrows断言允许我们以清晰和简单的方式断言一个可执行文件是否抛出指定的异常类型。

Let’s see how we can assert a thrown exception:

让我们看看我们如何断言一个被抛出的异常。

@Test
void whenAssertingException_thenThrown() {
    Throwable exception = assertThrows(
      IllegalArgumentException.class, 
      () -> {
          throw new IllegalArgumentException("Exception message");
      }
    );
    assertEquals("Exception message", exception.getMessage());
}

The assertion will fail if no exception is thrown, or if an exception of a different type is thrown.

如果没有抛出异常,或者抛出了不同类型的异常,断言将失败。

4.12. assertTimeout and assertTimeoutPreemptively

4.12.assertTimeoutassertTimeoutPreemptively

In case we want to assert that the execution of a supplied Executable ends before a given Timeout, we can use the assertTimeout assertion:

如果我们想断言提供的Executable的执行在给定的Timeout之前结束,我们可以使用assertTimeout断言。

@Test
void whenAssertingTimeout_thenNotExceeded() {
    assertTimeout(
      ofSeconds(2), 
      () -> {
        // code that requires less than 2 minutes to execute
        Thread.sleep(1000);
      }
    );
}

However, with the assertTimeout assertion, the supplied executable will be executed in the same thread of the calling code. Consequently, execution of the supplier won’t be preemptively aborted if the timeout is exceeded.

然而,通过assertTimeout断言,提供的可执行文件将在调用代码的同一线程中执行。因此,如果超过了超时,供应商的执行不会被预先中止。

In case we want to be sure that execution of the executable will be aborted once it exceeds the timeout, we can use the assertTimeoutPreemptively assertion.

如果我们想确保可执行文件的执行一旦超过超时就会被终止,我们可以使用assertTimeoutPreemptively断言。

Both assertions can accept, instead of an Executable, a ThrowingSupplier, representing any generic block of code that returns an object and that can potentially throw a Throwable.

这两个断言都可以接受,而不是一个Executable,一个ThrowingSupplier,代表任何返回对象并可能抛出Throwable的通用代码块。

5. Conclusion

5.结论

In this tutorial, we covered all the assertions available in both JUnit 4 and JUnit 5.

在本教程中,我们涵盖了JUnit 4和JUnit 5中可用的所有断言。

We highlighted briefly the improvements made in JUnit 5, with the introductions of new assertions and the support of lambdas.

我们简要地强调了JUnit 5中的改进,引入了新的断言和对lambdas的支持。

As always, the complete source code for this article is available over on GitHub.

与往常一样,本文的完整源代码可在GitHub上获得over