Oracle 到 PostgreSQL 的参考分区迁移实践
Source: InfoQ - Backend
JUnit团队发布了JUnit 6.0.0(2025年9月30日公开可用),统一了Platform、Jupiter和Vintage的版本号,并将最低Java版本提升至17(对于Kotlin测试代码则是Kotlin 2.2)。此更新增加了对Kotlin suspend测试的原生支持,新的CancellationToken API在ConsoleLauncher中支持快速失败执行,内置Java Flight Recorder(JFR)监听器,跨模块采用JSpecify空值注解,以及切换到FastCSV,用于CSV驱动的参数化测试。Vintage模块仍是用于JUnit 4的桥梁,但现已被弃用。
对于Kotlin用户来说,最明显的改进是直接支持suspend。以前,协程测试经常将主体包装在runBlocking中;使用JUnit 6时,开发者可以在测试和生命周期方法上声明suspend,并直接调用suspending API。这消除了样板代码,使协程测试看起来像它们所练习的生产代码。
考虑以下代码片段:
// Before JUnit 6@Testfun foo() = runBlocking {delay(1000)assertEquals(1, 1)}
// With JUnit 6@Testsuspend fun foo() {delay(1000) // suspend call works directlyassertEquals(1, 1)}
在执行语义方面,JUnit 6为嵌套类定义了一个确定性的、有意不明显的顺序。它还引入了MethodOrderer.Default和ClassOrderer.Default,并将@TestMethodOrder继承到@Nested类中。开发者现在也可以使用@TestClassOrder和@Order为嵌套类施加顺序。
以下示例在SecondaryTests之前运行PrimaryTests:
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空值注解来明确指示哪些方法参数、返回类型和字段可以为空。这为IDE提供更好的支持,提高了编译时安全性,并为从正确的可空/非可空类型区分中受益的Kotlin用户提供了更精确的文档。
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/构建工具中使用原生的Plaform集成或直接采用Jupiter;Vintage现在只作为临时的桥接,已被正式弃用。对于要升级到5.x版本的团队,可以参考该迁移wiki。
对于大多数已在使用Java 17和JUnit 5.14的团队来说,采用该新版本应该是一个常规的依赖项升级,随后的工作包括快速的试运行,现代化任何构建插件(例如,Surefire/Failsafe ≥ 3.0),并验证由CSV驱动的测试。Kotlin用户可以通过直接的suspend方法简化协程测试,JFR集成变得更容易采用,以便于性能调查。仍在使用JUnit 4的团队应该计划迁移工作,因为Vintage的弃用标志着那条兼容性路径的结束。
原文链接:JUnit 6.0.0 Ships with Java 17 Baseline, Cancellation API, and Kotlin suspend Support