Junit 5 学习笔记
Junit 5
总体架构
使用 Junit 5
如何在 Maven 中配置 Junit 5 的依赖: 咱的Maven项目能用Junit5吗? - 剑道子羽 - 博客园
案例演示: Junit5 新特性你用过多少? - 云+社区 - 腾讯云
系列教程: JUnit5学习之八:综合进阶(终篇)_程序员欣宸的博客-CSDN博客
API 总览: JUnit5单元测试框架的使用教程与简单实例_pan_junbiao的博客-CSDN博客_junit5单元测试实例
笔记
- @Test 注解不能测试 private 所修饰的方法
Demo
前置、后置测试
import org.junit.jupiter.api.*;
@DisplayName("我的普通测试类")
@TestMethodOrder(MethodOrderer.MethodName.class)
public class MyFirstTestClass {
@BeforeAll
public static void init() {
System.out.println("静态方法初始化数据");
}
@AfterAll
public static void destroy() {
System.out.println("静态方法清理数据");
}
@BeforeEach
public void beforeCase() {
System.out.println("测试用例准备开始");
}
@AfterEach
public void afterCase() {
System.out.println("测试用例已经结束");
}
@DisplayName("我的第一个测试用例")
@Test
void testFirstCase() {
System.out.println("First Test Case");
}
@DisplayName("我的第二个测试用例(重复测试)")
@RepeatedTest(value = 3, name = RepeatedTest.LONG_DISPLAY_NAME)
void testSecondCase() {
System.out.println("Second Test Case");
}
@DisplayName("我的第三个测试")
@Disabled
@Test
void testThirdCase() {
System.out.println("Third Test Case");
}
@Nested
@DisplayName("第一个内嵌测试类")
class FirstNestTest {
@Test
void test() {
System.out.println("第一个内嵌测试类执行测试");
}
}
}
断言测试
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import java.time.Duration;
import java.time.temporal.ChronoUnit;
@DisplayName("我的断言测试类")
public class MySecondTestClass {
@DisplayName("断言分组测试")
@Test
void testGroupAssertions() {
int[] numbers = {0, 1, 2, 3, 4};
Assertions.assertAll("numbers",
() -> Assertions.assertEquals(numbers[1], 1),
() -> Assertions.assertEquals(numbers[3], 3),
() -> Assertions.assertEquals(numbers[4], 4)
);
}
@Test
void testTrue() {
Assertions.assertTrue(Math.random() > -1);
}
@DisplayName("异步超时方法测试(超时直接中断线程, 1秒后返回错误)")
@Test
void testTimeoutPreemptively() {
Assertions.assertTimeoutPreemptively(Duration.of(1, ChronoUnit.SECONDS),
() -> Thread.sleep(5000)
);
}
@DisplayName("超时方法测试(一直等待线程执行结束, 5秒后返回错误)")
@Test
void testTimeout() {
Assertions.assertTimeout(Duration.of(1, ChronoUnit.SECONDS),
() -> Thread.sleep(5000)
);
}
@DisplayName("测试捕获的异常")
@Test
void assertThrowsException() {
String str = null;
Assertions.assertThrows(IllegalArgumentException.class, () -> {
Integer.valueOf(str);
});
}
}
假定测试
import org.junit.jupiter.api.Assumptions;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
@DisplayName("我的假定测试类")
public class MyThirdTestClass {
@Test
void testAssumptions() {
Assumptions.assumeTrue(Math.random() < 0, "未通过假定, 跳过该测试用例");
System.out.println("skip me, cannot print");
}
}
参数化测试
import org.junit.jupiter.api.*;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.converter.JavaTimeConversionPattern;
import org.junit.jupiter.params.provider.*;
import java.time.LocalDate;
@DisplayName("我的参数化测试类")
public class MyForthTestClass {
@DisplayName("测试多次传递 int 类型参数")
@ParameterizedTest
@ValueSource(ints = {2, 4, 6, 8})
void testNumberShouldBeEven(int num) {
Assertions.assertEquals(0, num % 2);
}
@DisplayName("测试传递 null 作为参数")
@ParameterizedTest
@NullSource
void testNullValue(Object o) {
Assertions.assertNull(o);
}
@DisplayName("测试传递空字符串作为参数")
@ParameterizedTest
@EmptySource
void testEmptyValue(String str) {
Assertions.assertEquals(0, str.length());
}
@DisplayName("测试传递 null 和空字符串作为参数")
@ParameterizedTest
@NullAndEmptySource
void testNullOrEmptyValue(String str) {
Assertions.assertTrue(() -> null == str || str.length() == 0);
}
@DisplayName("测试多次传递字符串参数")
@ParameterizedTest
@ValueSource(strings = {"Effective Java", "Code Complete", "Clean Code"})
void testStringNotEmpty(String str) {
Assertions.assertNotEquals(0, str.length());
}
@DisplayName("指定转换器, 将 String 转为 LocalDate 型入参")
@ParameterizedTest
@ValueSource(strings = { "01.01.2021", "31.12.2021" })
void argumentConversionWithConverterTest(
@JavaTimeConversionPattern("dd.MM.yyyy") LocalDate candidate) {
Assertions.assertEquals(2021, candidate.getYear());
}
@DisplayName("测试使用 Cvs 格式传递多个参数")
@Nested
class TestCvsSource {
@ParameterizedTest
@CsvSource({",14"})
void testUserNameIsNull(String name, int age) {
Assertions.assertNull(name);
}
@ParameterizedTest
@CsvSource({"'',14"})
void testUserNameIsEmpty(String name, int age) {
Assertions.assertEquals(0, name.length());
}
@ParameterizedTest
@CsvSource({"zhangsan,14", "lisi,20"})
void testUserInfoLegal(String name, int age) {
Assertions.assertAll(
() -> Assertions.assertNotNull(name),
() -> Assertions.assertNotEquals(0, name.length()),
() -> Assertions.assertTrue(age > 0)
);
}
}
}
条件测试
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.*;
public class MyFifthTestClass {
@Test
@EnabledOnJre(JRE.JAVA_8)
void testConditionJRE8() {
System.out.println("当前为 JRE8");
}
@Test
@EnabledOnJre(JRE.JAVA_11)
void testConditionJRE11() {
System.out.println("当前为 JRE11");
}
@Test
@EnabledOnOs(OS.WINDOWS)
void testConditionWindows() {
System.out.println("当前为 Windows 操作系统");
}
@Test
@DisabledOnOs(OS.WINDOWS)
void testConditionSkipOnWindows() {
System.out.println("Windows 操作系统不执行该测试用例");
}
}
并发测试
...