JUnit 6.0.0发布:Java 17基线、取消API与Kotlin协程支持

JUnit团队发布了JUnit 6.0.0(2025年9月30日GA),统一了Platform、Jupiter和Vintage的版本号,并将最低要求提升至Java 17(Kotlin测试代码需Kotlin 2.2)。本次更新增加了对Kotlin挂起测试的原生支持、带有ConsoleLauncher快速失败执行的新CancellationToken API、内置Java Flight Recorder(JFR)监听器、跨模块采用JSpecify空值注解,以及切换到FastCSV进行CSV驱动的参数化测试。Vintage作为JUnit 4的桥梁保留,但现已弃用。

对Kotlin用户而言,最显著的改进是直接挂起支持。此前,协程测试通常将函数体包裹在runBlocking中;而JUnit 6允许开发者在测试和生命周期方法上声明suspend,并直接调用挂起API。这消除了样板代码,使协程测试读起来更像它们所测试的生产代码。

考虑以下代码片段:

// JUnit 6之前
@Test
fun foo() = runBlocking {
    delay(1000)
    assertEquals(1, 1)
}

// 使用JUnit 6
@Test
suspend fun foo() {
    delay(1000) // 直接支持挂起调用
    assertEquals(1, 1)
}

在执行语义方面,JUnit 6为嵌套类定义了确定性的、故意非显而易见的顺序。它还引入了MethodOrderer.Default和ClassOrderer.Default,并将@TestMethodOrder继承到@Nested类中。开发者现在还可以使用@TestClassOrder与@Order为嵌套类施加顺序。

以下示例先运行PrimaryTests,再运行SecondaryTests:

import org.junit.jupiter.api.*;

@TestClassOrder(ClassOrderer.OrderAnnotation.class)
class OrderedNestedTestClassesDemo {

    @Nested @Order(1)
    class PrimaryTests {
        @Test void test1() {}
    }

    @Nested @Order(2)
    class SecondaryTests {
        @Test void test2() {}
    }
}

所有JUnit模块现在使用JSpecify空值注解来显式指示哪些方法参数、返回类型和字段可以为空。这为Kotlin用户提供了更好的IDE支持、改进的编译时安全性以及更精确的文档,使他们受益于适当的可空/非空类型区分。

JUnit 6从无人维护的univocity-parsers库迁移到FastCSV,用于@CsvSource和@CsvFileSource注解。FastCSV速度显著更快,符合RFC 4180标准,零依赖,并为格式错误的CSV数据提供更好的错误报告。此更改提高了CSV解析行为和整体测试执行性能的一致性。

取消和提前退出行为也得到显著升级。平台现在公开CancellationToken,启动器将其传递给引擎。开发者可以连接自己的监听器以在第一次失败时取消运行,而ConsoleLauncher添加了自动执行此操作的--fail-fast标志。以下代码片段展示了使用新的LauncherExecutionRequest API的监听器驱动方法。像Jupiter和Suite这样的引擎会遵守令牌,因此执行会干净地中止。

import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass;
import static org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder.discoveryRequest;
import static org.junit.platform.launcher.core.LauncherExecutionRequestBuilder.executionRequest;

import java.io.PrintWriter;

import org.junit.platform.engine.CancellationToken;
import org.junit.platform.engine.TestExecutionResult;
import org.junit.platform.launcher.*;
import org.junit.platform.launcher.core.LauncherFactory;
import org.junit.platform.launcher.listeners.SummaryGeneratingListener;

public class FailFastLauncher {

    static void main() {
        CancellationToken token = CancellationToken.create();

        TestExecutionListener failFast = new TestExecutionListener() {
            @Override
            public void executionFinished(TestIdentifier id, TestExecutionResult result) {
                if (result.getStatus() == TestExecutionResult.Status.FAILED) {
                    token.cancel();
                }
            }
        };

        SummaryGeneratingListener summary = new SummaryGeneratingListener();

        LauncherDiscoveryRequest discover = discoveryRequest()
                .selectors(selectClass(FastFailDemoTest.class))
                .build();

        LauncherExecutionRequest exec = executionRequest(discover)
                .cancellationToken(token)
                .listeners(failFast, summary)
                .build();

        try (LauncherSession session = LauncherFactory.openSession()) {
            session.getLauncher().execute(exec);
        }

        summary.getSummary().printTo(new PrintWriter(System.out, true));
    }
}

JFR支持现在内置在启动器的org.junit.platform.launcher.jfr下,取代了旧的junit-platform-jfr工件。开发者可以在启动测试时开始JFR记录,然后在JDK Mission Control或*.jfr工具中检查发现和执行事件,而无需添加任何额外依赖。详细信息记录在用户指南的“Flight Recorder Support”下。

6.0.0版本移除了长期弃用的junit-platform-runner(JUnit 4运行器)和各种传统的反射和运行器API。团队建议使用IDE/构建工具中的原生平台集成或直接采用Jupiter;Vintage仅作为临时桥梁保留,现已正式弃用。团队可从5.x升级的迁移指南可在wiki上获取。

对于大多数已经使用Java 17和JUnit 5.14的团队来说,采用应该是一个常规的依赖项升级,随后进行快速试运行,现代化任何构建插件(例如Surefire/Failsafe ≥ 3.0),并验证CSV驱动的测试。Kotlin用户可以通过直接挂起方法简化协程测试,并且JFR集成变得更易于采用以进行性能调查。仍在使用JUnit 4的团队应计划迁移工作,因为Vintage的弃用标志着该兼容性路径的结束。
更多精彩内容 请关注我的个人公众号 公众号(办公AI智能小助手)
对网络安全、黑客技术感兴趣的朋友可以关注我的安全公众号(网络安全技术点滴分享)

公众号二维码

公众号二维码

posted @ 2025-10-22 12:04  qife  阅读(6)  评论(0)    收藏  举报