这些方法都有多个重载方法,可以提供额外的消息来作为断言不满足时的提示消息,还可以接受 Java 8 中的 Supplier 接口来获取要判断的值和显示的消息。清单 4 中给出了简单断言的使用示例。
清单 4. 简单断言
@Test
@DisplayName("simple assertion")
public void simple() {
assertEquals(3, 1 + 2, "simple math");
assertNotEquals(3, 1 + 1);
assertNotSame(new Object(), new Object());
Object obj = new Object();
assertSame(obj, obj);
assertFalse(1 > 2);
assertTrue(1 < 2);
assertNull(null);
assertNotNull(new Object());
}
第二类是通过 assertArrayEquals 方法来判断两个对象或原始类型的数组是否相等,如清单 5 所示。
清单 5. assertArrayEquals 方法的示例
@Test
@DisplayName("array assertion")
public void array() {
assertArrayEquals(new int[]{1, 2}, new int[] {1, 2});
}
第三类是通过 assertAll 方法来判断一组断言是否满足。assertAll 方法接受多个 org.junit.jupiter.api.Executable 函数式接口的实例作为要验证的断言,可以通过 lambda 表达式很容易的提供这些断言,如清单 6 所示。
清单 6. assertAll 方法的示例
@Test
@DisplayName("assert all")
public void all() {
assertAll("Math",
() -> assertEquals(2, 1 + 1),
() -> assertTrue(1 > 0)
);
}
第四类是通过 assertThrows 或 expectThrows 来判断是否抛出期望的异常类型。两个方法的参数都是所期望的异常类型和对应的 Executable 接口的实现对象,区别在于 expectThrows 方法会返回抛出的异常对象。在清单 7 中,1/0 会抛出 ArithmeticException 异常,assertThrows 用来验证这一点。
清单 7. assertThrows 和 expectThrows 方法的示例
@Test
@DisplayName("throws exception")
public void exception() {
assertThrows(ArithmeticException.class, () -> System.out.println(1 / 0));
}
第五类是 fail 方法,用来使一个测试方法失败。清单 8 中的测试会直接失败。
清单 8. 通过 fail 方法直接使得测试失败
@Test
@DisplayName("fail")
public void shouldFail() {
fail("This should fail");
}
JUnit 5 前置条件
JUnit 5 中的前置条件(assumptions)类似于断言,不同之处在于不满足的断言会使得测试方法失败,而不满足的前置条件只会使得测试方法的执行终止。前置条件可以看成是测试方法执行的前提,当该前提不满足时,没有继续执行的必要。在清单 9 中,assumeTrue 和 assumFalse 确保给定的条件为 true 或 false,不满足条件会使得测试执行终止。assumingThat 的参数是表示条件的布尔值和对应的 Executable 接口的实现对象。只有条件满足时,Executable 对象才会被执行;当条件不满足时,测试执行并不会终止。
清单 9. JUnit 5 前置条件
@DisplayName("Assumptions")
public class AssumptionsTest {
private final String environment = "DEV";
@Test
@DisplayName("simple")
public void simpleAssume() {
assumeTrue(Objects.equals(this.environment, "DEV"));
assumeFalse(() -> Objects.equals(this.environment, "PROD"));
}
@Test
@DisplayName("assume then do")
public void assumeThenDo() {
assumingThat(
Objects.equals(this.environment, "DEV"),
() -> System.out.println("In DEV")
);
}
}
嵌套测试
JUnit 5 可以通过 Java 中的内部类和@Nested 注解实现嵌套测试,从而可以更好的把相关的测试方法组织在一起。在内部类中可以使用@BeforeEach 和@AfterEach 注解,而且嵌套的层次没有限制。清单 10 中给出了使用嵌套测试的示例,用来测试 HashMap 的功能。
清单 10. 嵌套测试
@DisplayName("Nested tests for HashMap")
public class MapNestedTest {
Map<String, Object> map;
@Nested
@DisplayName("when a new")
class WhenNew {
@BeforeEach
void create() {
map = new HashMap<>();
}
@Test
@DisplayName("is empty")
void isEmpty() {
assertTrue(map.isEmpty());
}
@Nested
@DisplayName("after adding a new entry")
class AfterAdd {
String key = "key";
Object value = "value";
@BeforeEach
void add() {
map.put(key, value);
}
@Test
@DisplayName("is not empty")
void isNotEmpty() {
assertFalse(map.isEmpty());
}
@Test
@DisplayName("returns value when getting by key")
void returnValueWhenGettingByKey() {
assertEquals(value, map.get(key));
}
@Nested
@DisplayName("after removing the entry")
class AfterRemove {
@BeforeEach
void remove() {
map.remove(key);
}
@Test
@DisplayName("is empty now")
void isEmpty() {
assertTrue(map.isEmpty());
}
@Test
@DisplayName("returns null when getting by key")
void returnNullForKey() {
assertNull(map.get(key));
}
}
}
}
}
依赖注入
在 JUnit 5 之前,标准的测试类和测试方法是不允许有额外的参数的。这个限制在 JUnit 5 被取消了。JUnit 5 除了提供内置的标准参数之外,还可以通过扩展机制来支持额外的参数。
当参数的类型是 org.junit.jupiter.api.TestInfo 时,JUnit 5 会在运行测试时提供一个 TestInfo 接口的对象。通过 TestInfo 接口,可以获取到当前测试的相关信息,包括显示名称、标签、测试类和测试方法,如清单 11 所示。
清单 11. TestInfo 依赖注入
@Test
@DisplayName("test info")
public void testInfo(final TestInfo testInfo) {
System.out.println(testInfo.getDisplayName());
}
当参数的类型是 org.junit.jupiter.api.TestReporter 时,在运行测试时,通过作为参数传入的 TestReporter 接口对象,来输出额外的键值对信息。这些信息可以被测试执行的监听器 TestExecutionListener 处理,也可以被输出到测试结果报告中,如清单 12 所示。
清单 12. TestReporter 依赖注入
@Test
@DisplayName("test reporter")
public void testReporter(final TestReporter testReporter) {
testReporter.publishEntry("name", "Alex");
}
除了 TestInfo 和 TestReporter 之外,也可以通过 JUnit 5 的扩展机制来添加对其他类型参数的支持。将在下面关于 JUnit 5 扩展机制的一节中进行介绍。