Skip to content

从 JUnit 4 升级到 JUnit 5 需要做一些改动,因为 JUnit 5 与 JUnit 4 在结构、注解和 API 上有一些重要的区别。下面是升级步骤以及需要关注的主要变化。

1. 添加 JUnit 5 依赖

首先,确保你的项目包含了 JUnit 5 的依赖。如果你使用的是 Maven 或 Gradle,首先需要在构建文件中添加 JUnit 5 相关的依赖。

对于 Maven:

xml
<dependencies>
    <!-- JUnit 5依赖 -->
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter-api</artifactId>
        <version>5.7.2</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter-engine</artifactId>
        <version>5.7.2</version>
        <scope>test</scope>
    </dependency>

    <!-- JUnit Platform Console (用于运行测试的命令行工具) -->
    <dependency>
        <groupId>org.junit.platform</groupId>
        <artifactId>junit-platform-launcher</artifactId>
        <version>1.7.2</version>
        <scope>test</scope>
    </dependency>
</dependencies>
<dependencies>
    <!-- JUnit 5依赖 -->
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter-api</artifactId>
        <version>5.7.2</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter-engine</artifactId>
        <version>5.7.2</version>
        <scope>test</scope>
    </dependency>

    <!-- JUnit Platform Console (用于运行测试的命令行工具) -->
    <dependency>
        <groupId>org.junit.platform</groupId>
        <artifactId>junit-platform-launcher</artifactId>
        <version>1.7.2</version>
        <scope>test</scope>
    </dependency>
</dependencies>

对于 Gradle:

groovy
dependencies {
    // JUnit 5依赖
    testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.2'
    testImplementation 'org.junit.jupiter:junit-jupiter-engine:5.7.2'
    testRuntimeOnly 'org.junit.platform:junit-platform-launcher:1.7.2'
}
dependencies {
    // JUnit 5依赖
    testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.2'
    testImplementation 'org.junit.jupiter:junit-jupiter-engine:5.7.2'
    testRuntimeOnly 'org.junit.platform:junit-platform-launcher:1.7.2'
}

2. JUnit 4 和 JUnit 5 注解的差异

JUnit 5 引入了新的注解替代了 JUnit 4 中的注解。以下是一些主要注解的变化:

JUnit 4 注解JUnit 5 注解说明
@Test@Test保持一致,但需要导入 org.junit.jupiter.api.Test
@Before@BeforeEach在每个测试方法之前运行
@After@AfterEach在每个测试方法之后运行
@BeforeClass@BeforeAll在所有测试之前运行
@AfterClass@AfterAll在所有测试之后运行
@Ignore@Disabled禁用测试
@RunWithJUnit 5 不再需要JUnit 5 不需要使用 @RunWith 注解。

3. 升级代码示例

3.1 JUnit 4 示例:

java
import org.junit.Before;
import org.junit.After;
import org.junit.Test;

public class MyTest {

    @Before
    public void setUp() {
        // 初始化工作
    }

    @Test
    public void testSomething() {
        // 测试代码
    }

    @After
    public void tearDown() {
        // 清理工作
    }
}
import org.junit.Before;
import org.junit.After;
import org.junit.Test;

public class MyTest {

    @Before
    public void setUp() {
        // 初始化工作
    }

    @Test
    public void testSomething() {
        // 测试代码
    }

    @After
    public void tearDown() {
        // 清理工作
    }
}

3.2 JUnit 5 示例:

java
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.Disabled;

public class MyTest {

    @BeforeEach
    public void setUp() {
        // 初始化工作
    }

    @Test
    public void testSomething() {
        // 测试代码
    }

    @AfterEach
    public void tearDown() {
        // 清理工作
    }

    @Test
    @Disabled("This test is disabled for now")
    public void disabledTest() {
        // 禁用测试
    }
}
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.Disabled;

public class MyTest {

    @BeforeEach
    public void setUp() {
        // 初始化工作
    }

    @Test
    public void testSomething() {
        // 测试代码
    }

    @AfterEach
    public void tearDown() {
        // 清理工作
    }

    @Test
    @Disabled("This test is disabled for now")
    public void disabledTest() {
        // 禁用测试
    }
}

4. 使用 JUnit 5 的测试生命周期

JUnit 5 引入了更多的测试生命周期注解来代替 JUnit 4 的 @Before@After 等。

  • @BeforeEach:替代了 @Before,表示在每个测试方法之前运行。
  • @AfterEach:替代了 @After,表示在每个测试方法之后运行。
  • @BeforeAll:替代了 @BeforeClass,表示在所有测试之前运行一次。
  • @AfterAll:替代了 @AfterClass,表示在所有测试之后运行一次。

5. 参数化测试

JUnit 5 提供了更强大的参数化测试支持。JUnit 4 使用 @RunWith(Parameterized.class) 进行参数化测试,而 JUnit 5 使用 @ParameterizedTest 注解。

5.1 JUnit 4 参数化测试示例:

java
import org.junit.runners.Parameterized;
import org.junit.Test;
import org.junit.runner.RunWith;

@RunWith(Parameterized.class)
public class ParameterizedTest {

    private int input;
    private int expectedOutput;

    public ParameterizedTest(int input, int expectedOutput) {
        this.input = input;
        this.expectedOutput = expectedOutput;
    }

    @Parameterized.Parameters
    public static Object[][] data() {
        return new Object[][] {
            {1, 2},
            {2, 4},
            {3, 6}
        };
    }

    @Test
    public void testMultiplication() {
        assertEquals(expectedOutput, input * 2);
    }
}
import org.junit.runners.Parameterized;
import org.junit.Test;
import org.junit.runner.RunWith;

@RunWith(Parameterized.class)
public class ParameterizedTest {

    private int input;
    private int expectedOutput;

    public ParameterizedTest(int input, int expectedOutput) {
        this.input = input;
        this.expectedOutput = expectedOutput;
    }

    @Parameterized.Parameters
    public static Object[][] data() {
        return new Object[][] {
            {1, 2},
            {2, 4},
            {3, 6}
        };
    }

    @Test
    public void testMultiplication() {
        assertEquals(expectedOutput, input * 2);
    }
}

5.2 JUnit 5 参数化测试示例:

java
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;

public class ParameterizedTest {

    @ParameterizedTest
    @ValueSource(ints = {1, 2, 3})
    void testMultiplication(int input) {
        assertTrue(input * 2 == input + input);
    }
}
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;

public class ParameterizedTest {

    @ParameterizedTest
    @ValueSource(ints = {1, 2, 3})
    void testMultiplication(int input) {
        assertTrue(input * 2 == input + input);
    }
}

6. 启动器(Launcher)和运行器(Runner)

JUnit 5 也不再使用 @RunWith,而是使用新的测试引擎来启动测试。默认情况下,JUnit 5 会自动识别并执行测试方法。

如果需要在 JUnit 5 中控制测试执行,可以使用 JUnitPlatform 来作为测试引擎。

7. 迁移过程中的常见问题

  • JUnit 4 和 JUnit 5 混用:你可以在同一个项目中同时使用 JUnit 4 和 JUnit 5。通过依赖 junit-vintage-engine,JUnit 5 可以运行 JUnit 4 的测试。

    xml
    <dependency>
        <groupId>org.junit.vintage</groupId>
        <artifactId>junit-vintage-engine</artifactId>
        <version>5.7.2</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.junit.vintage</groupId>
        <artifactId>junit-vintage-engine</artifactId>
        <version>5.7.2</version>
        <scope>test</scope>
    </dependency>
  • JUnit 5 不支持 @RunWith:如果你使用了 @RunWith 注解,需要改成 JUnit 5 推荐的方式。

8. 小结

  1. 迁移依赖:确保项目使用 JUnit 5 的依赖。
  2. 更换注解:将 JUnit 4 的注解改为 JUnit 5 的对应注解。
  3. 启用参数化测试:JUnit 5 提供了更强大的参数化测试功能。
  4. 移除 @RunWith:JUnit 5 不再使用 @RunWith,直接使用 JUnit 5 引擎。

通过上述步骤,你可以将 JUnit 4 项目成功迁移到 JUnit 5,享受其新特性和更强大的功能。

JUnit 4 升级到 JUnit 5

JUnit 4 升级到 JUnit 5 时,通常 Spring Boot 项目也需要进行相应的升级。因为 Spring Boot 使用的 测试框架(比如 spring-boot-starter-test)通常会绑定到 JUnit 版本上,因此如果你升级了 JUnit,你可能也需要升级 Spring Boot 以确保兼容性。

以下是一些关于是否需要升级 Spring Boot 以及如何进行升级的注意事项:

1. Spring Boot 与 JUnit 5 兼容性

  • Spring Boot 2.2 及更高版本:Spring Boot 2.2 及之后的版本原生支持 JUnit 5,因此如果你使用的是 Spring Boot 2.2 或更高版本,你可以直接升级到 JUnit 5,而不需要做额外的配置。

  • Spring Boot 2.1 及之前版本:这些版本默认集成的是 JUnit 4。如果你在这些版本中使用 JUnit 5,你需要手动配置 JUnit 5 支持,或者升级到 Spring Boot 2.2 或更高版本。

2. Spring Boot 版本升级

如果你的项目使用的是 Spring Boot 2.1 或更低版本,你需要升级 Spring Boot 版本,以便原生支持 JUnit 5。下面是升级步骤:

升级 Spring Boot 版本:

  1. 修改 pom.xml(Maven)中的 Spring Boot 版本

    xml
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.5.0</version> <!-- 升级到 2.2 或更高版本 -->
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.5.0</version> <!-- 升级到 2.2 或更高版本 -->
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
  2. 修改 build.gradle(Gradle)中的 Spring Boot 版本

    groovy
    dependencies {
        implementation 'org.springframework.boot:spring-boot-starter:2.5.0' // 升级到 2.2 或更高版本
    }
    dependencies {
        implementation 'org.springframework.boot:spring-boot-starter:2.5.0' // 升级到 2.2 或更高版本
    }

3. 确保 spring-boot-starter-test 版本兼容 JUnit 5

Spring Boot 2.2 及更高版本会自动支持 JUnit 5。如果你使用的是 Spring Boot 2.2+spring-boot-starter-test 已经包含了 JUnit 5,因此你无需做额外配置。

对于 Spring Boot 2.1 及以下版本,如果你想使用 JUnit 5,你需要确保 spring-boot-starter-test 包中包含 junit-jupiter 依赖。可以通过以下方式添加:

Maven 配置(适用于 Spring Boot 2.1 或更低版本):

xml
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <version>2.1.0.RELEASE</version> <!-- 保证使用适当版本 -->
        <scope>test</scope>
    </dependency>

    <!-- 添加 JUnit 5 依赖 -->
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter-api</artifactId>
        <version>5.7.2</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter-engine</artifactId>
        <version>5.7.2</version>
        <scope>test</scope>
    </dependency>
</dependencies>
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <version>2.1.0.RELEASE</version> <!-- 保证使用适当版本 -->
        <scope>test</scope>
    </dependency>

    <!-- 添加 JUnit 5 依赖 -->
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter-api</artifactId>
        <version>5.7.2</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter-engine</artifactId>
        <version>5.7.2</version>
        <scope>test</scope>
    </dependency>
</dependencies>

Gradle 配置(适用于 Spring Boot 2.1 或更低版本):

groovy
dependencies {
    testImplementation 'org.springframework.boot:spring-boot-starter-test:2.1.0.RELEASE' // 使用适当版本
    testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.2'
    testImplementation 'org.junit.jupiter:junit-jupiter-engine:5.7.2'
}
dependencies {
    testImplementation 'org.springframework.boot:spring-boot-starter-test:2.1.0.RELEASE' // 使用适当版本
    testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.2'
    testImplementation 'org.junit.jupiter:junit-jupiter-engine:5.7.2'
}

4. Spring Test 和 JUnit 5 配合使用

Spring 也对 JUnit 5 提供了更好的支持,特别是通过 @ExtendWith 注解替代了 JUnit 4 中的 @RunWith(SpringRunner.class)。Spring 5 提供了 @ExtendWith(SpringExtension.class) 来使 Spring 管理测试上下文。

JUnit 5 + Spring Boot 测试示例:

java
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit.jupiter.SpringExtension;

@ExtendWith(SpringExtension.class)  // JUnit 5 的扩展
@SpringBootTest
public class MyServiceTest {

    @Autowired
    private MyService myService;

    @Test
    public void testServiceMethod() {
        // 测试代码
    }
}
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit.jupiter.SpringExtension;

@ExtendWith(SpringExtension.class)  // JUnit 5 的扩展
@SpringBootTest
public class MyServiceTest {

    @Autowired
    private MyService myService;

    @Test
    public void testServiceMethod() {
        // 测试代码
    }
}

5. 迁移到 Spring Boot 2.2 及更高版本的优势

  • JUnit 5 支持:Spring Boot 2.2 及更高版本已经内建对 JUnit 5 的支持,确保测试框架更新无缝集成。
  • 兼容性改进:Spring Boot 2.2 提供了对 JUnit 5 的更好支持,改进了启动性能以及与 Spring 组件的兼容性。

总结

  • 如果你使用的是 Spring Boot 2.2 或更高版本,则无需额外配置,直接升级到 JUnit 5 即可。
  • 如果你使用的是 Spring Boot 2.1 或更低版本,你需要升级 Spring Boot 版本至 2.2 或更高,或者手动配置 JUnit 5。
  • 对于测试类中的注解,Spring Boot 2.2 及更高版本支持 JUnit 5 的新注解,如 @ExtendWith(SpringExtension.class) 替代 JUnit 4 中的 @RunWith(SpringRunner.class)

因此,升级 Spring Boot 到适当的版本是确保与 JUnit 5 完全兼容的关键。

JUnit 5 与 Spring Boot 集成

Spring Boot 与 JUnit 5 的兼容性

  • 如果你使用的是 Spring Boot 2.2 或更高版本,则无需额外配置,直接升级到 JUnit 5 即可。
  • 如果你使用的是 Spring Boot 2.1 或更低版本,你需要升级 Spring Boot 版本至 2.2 或更高,或者手动配置 JUnit 5。
  • 对于测试类中的注解,Spring Boot 2.2 及更高版本支持 JUnit 5 的新注解,如 @ExtendWith(SpringExtension.class) 替代 JUnit 4 中的 @RunWith(SpringRunner.class)
  • 因此,升级 Spring Boot 到适当的版本是确保与 JUnit 5 完全兼容的关键。

JUnit 5 新特性

JUnit 5 相比于 JUnit 4 引入了许多新的功能和工具,显著提升了测试的灵活性、可扩展性和易用性。以下是 JUnit 5 中的一些重要新工具和特性。

1. JUnit 5 的模块化设计(Modular Architecture)

JUnit 5 引入了模块化架构,通过将其分成三个核心子模块,使得扩展和定制变得更加容易:

  1. JUnit Platform:负责测试引擎的启动和执行。它是 JUnit 5 的基础,可以运行 JUnit 4、JUnit 5、TestNG 等测试。
  2. JUnit Jupiter:包含 JUnit 5 的核心功能和测试引擎,支持新的注解和断言。
  3. JUnit Vintage:用于支持运行旧版的 JUnit 3 和 JUnit 4 测试用例。

示例

xml
<!-- 依赖于JUnit 5平台 -->
<dependency>
  <groupId>org.junit.platform</groupId>
  <artifactId>junit-platform-launcher</artifactId>
  <version>5.x.x</version>
  <scope>test</scope>
</dependency>
<!-- 依赖于JUnit 5平台 -->
<dependency>
  <groupId>org.junit.platform</groupId>
  <artifactId>junit-platform-launcher</artifactId>
  <version>5.x.x</version>
  <scope>test</scope>
</dependency>

JUnit 5 与 Spring Boot 集成

Spring Boot 与 JUnit 5 的兼容性

  • 如果你使用的是 Spring Boot 2.2 或更高版本,则无需额外配置,直接升级到 JUnit 5 即可。
  • 如果你使用的是 Spring Boot 2.1 或更低版本,你需要升级 Spring Boot 版本至 2.2 或更高,或者手动配置 JUnit 5。
  • 对于测试类中的注解,Spring Boot 2.2 及更高版本支持 JUnit 5 的新注解,如 @ExtendWith(SpringExtension.class) 替代 JUnit 4 中的 @RunWith(SpringRunner.class)
  • 因此,升级 Spring Boot 到适当的版本是确保与 JUnit 5 完全兼容的关键。

JUnit 5 新特性

JUnit 5 相比于 JUnit 4 引入了许多新的功能和工具,显著提升了测试的灵活性、可扩展性和易用性。以下是 JUnit 5 中的一些重要新工具和特性。

1. JUnit 5 的模块化设计(Modular Architecture)

JUnit 5 引入了模块化架构,通过将其分成三个核心子模块,使得扩展和定制变得更加容易:

  1. JUnit Platform:负责测试引擎的启动和执行。它是 JUnit 5 的基础,可以运行 JUnit 4、JUnit 5、TestNG 等测试。
  2. JUnit Jupiter:包含 JUnit 5 的核心功能和测试引擎,支持新的注解和断言。
  3. JUnit Vintage:用于支持运行旧版的 JUnit 3 和 JUnit 4 测试用例。

示例

xml

org.junit.platform junit-platform-launcher 5.x.x test

2. 新的注解(Annotations)

JUnit 5 引入了许多新的注解,提供了比 JUnit 4 更灵活的方式来编写和组织测试。

  • @Test:与 JUnit 4 相比,增加了一些新功能,如 @EnabledIf@DisabledIf 条件化测试。

  • @BeforeEach@AfterEach

    • @BeforeEach:用于在每个测试方法执行之前运行的代码。
    • @AfterEach:用于在每个测试方法执行之后运行的代码。

    相比于 JUnit 4 的 @Before@After,JUnit 5 的命名更加符合现代标准,并且支持更多灵活的配置。

    示例:

    java
    @BeforeEach
    void setup() {
        // 每个测试之前的初始化工作
    }
    
    @AfterEach
    void tearDown() {
        // 每个测试之后的清理工作
    }
    @BeforeEach
    void setup() {
        // 每个测试之前的初始化工作
    }
    
    @AfterEach
    void tearDown() {
        // 每个测试之后的清理工作
    }
  • @BeforeAll@AfterAll

    • @BeforeAll:用于在所有测试方法执行之前运行的代码(静态方法)。
    • @AfterAll:用于在所有测试方法执行之后运行的代码(静态方法)。

    示例:

    java
    @BeforeAll
    static void init() {
        // 只在所有测试方法执行之前运行一次
    }
    
    @AfterAll
    static void cleanUp() {
        // 只在所有测试方法执行之后运行一次
    }
    @BeforeAll
    static void init() {
        // 只在所有测试方法执行之前运行一次
    }
    
    @AfterAll
    static void cleanUp() {
        // 只在所有测试方法执行之后运行一次
    }

3. 条件化测试(Conditional Test Execution)

JUnit 5 引入了条件化执行测试的新注解,可以根据不同的条件来决定是否执行某个测试方法。

  • @EnabledIf:仅在满足条件时执行测试。
  • @DisabledIf:仅在条件不满足时跳过测试。

示例

java
@EnabledIf(expression = "#{systemProperties['os.name'].contains('Windows')}", reason = "Only runs on Windows")
    @Test
    void onlyWindowsTest() {
        // 仅在 Windows 上运行的测试
    }
    @DisabledIf(expression = "#{systemProperties['os.name'].contains('Linux')}", reason = "Doesn't run on Linux")
    @Test
    void disabledOnLinux() {
        // 在 Linux 上禁用的测试
    }
@EnabledIf(expression = "#{systemProperties['os.name'].contains('Windows')}", reason = "Only runs on Windows")
    @Test
    void onlyWindowsTest() {
        // 仅在 Windows 上运行的测试
    }
    @DisabledIf(expression = "#{systemProperties['os.name'].contains('Linux')}", reason = "Doesn't run on Linux")
    @Test
    void disabledOnLinux() {
        // 在 Linux 上禁用的测试
    }

4. 参数化测试(Parameterized Tests)

JUnit 5 引入了参数化测试,可以让同一个测试方法根据不同的参数多次执行。

  • @ParameterizedTest:通过 @ParameterizedTest 注解,可以让同一个测试方法根据不同的参数多次执行。

示例

java
@ParameterizedTest
@ValueSource(ints = {1, 2, 3})
void testWithDifferentValues(int number) {
    assertTrue(number > 0);
}
@ParameterizedTest
@ValueSource(ints = {1, 2, 3})
void testWithDifferentValues(int number) {
    assertTrue(number > 0);
}
  • @CsvSource@CsvFileSource:提供了两种方式来传递测试数据。

示例

java
@ParameterizedTest
@CsvSource({"apple, 1", "banana, 2"})
void testWithCsvSource(String fruit, int rank) {
    assertNotNull(fruit);
    assertTrue(rank > 0);
}
@ParameterizedTest
@CsvFileSource(resources = "/test-data.csv", numLinesToSkip = 1)
void testWithCsvFileSource(String fruit, int rank) {
    assertNotNull(fruit);
    assertTrue(rank > 0);
}
@ParameterizedTest
@CsvSource({"apple, 1", "banana, 2"})
void testWithCsvSource(String fruit, int rank) {
    assertNotNull(fruit);
    assertTrue(rank > 0);
}
@ParameterizedTest
@CsvFileSource(resources = "/test-data.csv", numLinesToSkip = 1)
void testWithCsvFileSource(String fruit, int rank) {
    assertNotNull(fruit);
    assertTrue(rank > 0);
}

5. 动态测试(Dynamic Tests)

JUnit 5 引入了动态测试(Dynamic Tests),允许在运行时动态创建测试方法,这比静态定义的测试方法更加灵活。

示例

java
@TestFactory
Stream<DynamicTest> dynamicTestsFromStream() {
    return Stream.of("apple", "banana", "cherry")
            .map(fruit -> DynamicTest.dynamicTest("Test " + fruit, () -> assertNotNull(fruit)));
}
@TestFactory
Stream<DynamicTest> dynamicTestsFromStream() {
    return Stream.of("apple", "banana", "cherry")
            .map(fruit -> DynamicTest.dynamicTest("Test " + fruit, () -> assertNotNull(fruit)));
}

6. 扩展机制(Extension Model)

JUnit 5 引入了强大的扩展机制,通过 @ExtendWith 注解,可以将自定义扩展(例如:生命周期管理、条件化执行、参数化等)应用到测试中。

示例

java
@ExtendWith(MyCustomExtension.class)
class MyTest {
    @Test
    void testMethod() {
        // 测试方法代码
    }
}
@ExtendWith(MyCustomExtension.class)
class MyTest {
    @Test
    void testMethod() {
        // 测试方法代码
    }
}

7. 测试报告与输出(Test Reporting and Output)

JUnit 5 提供了更加丰富的报告功能,可以与 JUnit Platform 集成,生成 HTML 和 XML 格式的测试报告,并且支持更灵活的日志输出。

8. 重复测试(@RepeatedTest)

JUnit 5 允许你将同一个测试方法重复执行多次,而不需要复制和粘贴代码。通过 @RepeatedTest 注解可以指定重复的次数。

示例

java
@RepeatedTest(5)
void repeatedTest() {
    assertTrue(true);
}
@RepeatedTest(5)
void repeatedTest() {
    assertTrue(true);
}

9. 超时(Timeout)

JUnit 5 提供了内建的超时测试功能,可以指定测试方法执行的最大时间。如果超时,测试将失败。

示例

java
@Test
@Timeout(2) // 单位为秒,表示2秒超时
void testWithTimeout() {
    // 代码如果超过2秒则会失败
}
@Test
@Timeout(2) // 单位为秒,表示2秒超时
void testWithTimeout() {
    // 代码如果超过2秒则会失败
}

总结

JUnit 5 相比于 JUnit 4 引入了很多新特性,主要包括:

  1. 更加模块化的设计(JUnit Platform、JUnit Jupiter、JUnit Vintage)。
  2. 新的注解和生命周期管理(如 @BeforeEach, @AfterEach, @BeforeAll, @AfterAll)。
  3. 参数化测试、动态测试和条件化测试等新功能。
  4. 增强的扩展机制,允许更容易地扩展和定制测试行为。

这些新工具和功能大大提升了 JUnit 5 在编写、执行和管理测试中的灵活性和可扩展性。