Upgrade to JUnit 6.0 RC3

See gh-35124
This commit is contained in:
Sam Brannen 2025-06-28 11:18:44 +02:00
parent 7edb0b3397
commit d84bf18408
13 changed files with 39 additions and 48 deletions

View File

@ -75,7 +75,7 @@ configure([rootProject] + javaProjects) { project ->
"https://hc.apache.org/httpcomponents-client-5.5.x/current/httpclient5/apidocs/", "https://hc.apache.org/httpcomponents-client-5.5.x/current/httpclient5/apidocs/",
"https://projectreactor.io/docs/test/release/api/", "https://projectreactor.io/docs/test/release/api/",
"https://junit.org/junit4/javadoc/4.13.2/", "https://junit.org/junit4/javadoc/4.13.2/",
"https://docs.junit.org/5.13.4/api/", "https://docs.junit.org/6.0.0-RC3/api/",
"https://www.reactive-streams.org/reactive-streams-1.0.3-javadoc/", "https://www.reactive-streams.org/reactive-streams-1.0.3-javadoc/",
//"https://javadoc.io/static/io.rsocket/rsocket-core/1.1.1/", //"https://javadoc.io/static/io.rsocket/rsocket-core/1.1.1/",
"https://r2dbc.io/spec/1.0.0.RELEASE/api/", "https://r2dbc.io/spec/1.0.0.RELEASE/api/",

View File

@ -19,7 +19,7 @@ dependencies {
api(platform("org.eclipse.jetty.ee11:jetty-ee11-bom:12.1.1")) api(platform("org.eclipse.jetty.ee11:jetty-ee11-bom:12.1.1"))
api(platform("org.jetbrains.kotlinx:kotlinx-coroutines-bom:1.10.2")) api(platform("org.jetbrains.kotlinx:kotlinx-coroutines-bom:1.10.2"))
api(platform("org.jetbrains.kotlinx:kotlinx-serialization-bom:1.9.0")) api(platform("org.jetbrains.kotlinx:kotlinx-serialization-bom:1.9.0"))
api(platform("org.junit:junit-bom:5.13.4")) api(platform("org.junit:junit-bom:6.0.0-RC3"))
api(platform("org.mockito:mockito-bom:5.19.0")) api(platform("org.mockito:mockito-bom:5.19.0"))
api(platform("tools.jackson:jackson-bom:3.0.0-rc10")) api(platform("tools.jackson:jackson-bom:3.0.0-rc10"))

View File

@ -18,6 +18,7 @@ package org.springframework.core.test.tools;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import org.jspecify.annotations.Nullable;
import org.junit.jupiter.api.extension.ExtensionContext; import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.api.extension.InvocationInterceptor; import org.junit.jupiter.api.extension.InvocationInterceptor;
import org.junit.jupiter.api.extension.ReflectiveInvocationContext; import org.junit.jupiter.api.extension.ReflectiveInvocationContext;
@ -44,7 +45,7 @@ import static org.junit.platform.launcher.EngineFilter.includeEngines;
class CompileWithForkedClassLoaderExtension implements InvocationInterceptor { class CompileWithForkedClassLoaderExtension implements InvocationInterceptor {
@Override @Override
public void interceptBeforeAllMethod(Invocation<Void> invocation, public void interceptBeforeAllMethod(Invocation<@Nullable Void> invocation,
ReflectiveInvocationContext<Method> invocationContext, ReflectiveInvocationContext<Method> invocationContext,
ExtensionContext extensionContext) throws Throwable { ExtensionContext extensionContext) throws Throwable {
@ -52,7 +53,7 @@ class CompileWithForkedClassLoaderExtension implements InvocationInterceptor {
} }
@Override @Override
public void interceptBeforeEachMethod(Invocation<Void> invocation, public void interceptBeforeEachMethod(Invocation<@Nullable Void> invocation,
ReflectiveInvocationContext<Method> invocationContext, ReflectiveInvocationContext<Method> invocationContext,
ExtensionContext extensionContext) throws Throwable { ExtensionContext extensionContext) throws Throwable {
@ -60,7 +61,7 @@ class CompileWithForkedClassLoaderExtension implements InvocationInterceptor {
} }
@Override @Override
public void interceptAfterEachMethod(Invocation<Void> invocation, public void interceptAfterEachMethod(Invocation<@Nullable Void> invocation,
ReflectiveInvocationContext<Method> invocationContext, ReflectiveInvocationContext<Method> invocationContext,
ExtensionContext extensionContext) throws Throwable { ExtensionContext extensionContext) throws Throwable {
@ -68,7 +69,7 @@ class CompileWithForkedClassLoaderExtension implements InvocationInterceptor {
} }
@Override @Override
public void interceptAfterAllMethod(Invocation<Void> invocation, public void interceptAfterAllMethod(Invocation<@Nullable Void> invocation,
ReflectiveInvocationContext<Method> invocationContext, ReflectiveInvocationContext<Method> invocationContext,
ExtensionContext extensionContext) throws Throwable { ExtensionContext extensionContext) throws Throwable {
@ -76,7 +77,7 @@ class CompileWithForkedClassLoaderExtension implements InvocationInterceptor {
} }
@Override @Override
public void interceptTestMethod(Invocation<Void> invocation, public void interceptTestMethod(Invocation<@Nullable Void> invocation,
ReflectiveInvocationContext<Method> invocationContext, ReflectiveInvocationContext<Method> invocationContext,
ExtensionContext extensionContext) throws Throwable { ExtensionContext extensionContext) throws Throwable {
@ -84,13 +85,13 @@ class CompileWithForkedClassLoaderExtension implements InvocationInterceptor {
() -> runTestWithModifiedClassPath(invocationContext, extensionContext)); () -> runTestWithModifiedClassPath(invocationContext, extensionContext));
} }
private void intercept(Invocation<Void> invocation, ExtensionContext extensionContext) private void intercept(Invocation<@Nullable Void> invocation, ExtensionContext extensionContext)
throws Throwable { throws Throwable {
intercept(invocation, extensionContext, Action.NONE); intercept(invocation, extensionContext, Action.NONE);
} }
private void intercept(Invocation<Void> invocation, ExtensionContext extensionContext, private void intercept(Invocation<@Nullable Void> invocation, ExtensionContext extensionContext,
Action action) throws Throwable { Action action) throws Throwable {
if (isUsingForkedClassPathLoader(extensionContext)) { if (isUsingForkedClassPathLoader(extensionContext)) {

View File

@ -110,6 +110,9 @@ test {
// `include` test filters and system properties are configured in // `include` test filters and system properties are configured in
// org.springframework.build.TestConventions in buildSrc. // org.springframework.build.TestConventions in buildSrc.
filter.excludeTestsMatching("*TestCase") filter.excludeTestsMatching("*TestCase")
// Override critical severity defined in TestConventions, since spring-test
// relies on the Vintage test engine for JUnit 4 support.
systemProperty("junit.platform.discovery.issue.severity.critical", "WARNING")
// Optionally configure Java Util Logging for the JUnit Platform. // Optionally configure Java Util Logging for the JUnit Platform.
// systemProperty("java.util.logging.manager", "org.apache.logging.log4j.jul.LogManager") // systemProperty("java.util.logging.manager", "org.apache.logging.log4j.jul.LogManager")
} }

View File

@ -169,7 +169,7 @@ public class SpringExtension implements BeforeAllCallback, AfterAllCallback, Tes
// re-validate all methods for the same test class multiple times. // re-validate all methods for the same test class multiple times.
Store store = context.getStore(AUTOWIRED_VALIDATION_NAMESPACE); Store store = context.getStore(AUTOWIRED_VALIDATION_NAMESPACE);
String errorMessage = store.getOrComputeIfAbsent(context.getRequiredTestClass(), testClass -> { String errorMessage = store.computeIfAbsent(context.getRequiredTestClass(), testClass -> {
Method[] methodsWithErrors = Method[] methodsWithErrors =
ReflectionUtils.getUniqueDeclaredMethods(testClass, autowiredTestOrLifecycleMethodFilter); ReflectionUtils.getUniqueDeclaredMethods(testClass, autowiredTestOrLifecycleMethodFilter);
return (methodsWithErrors.length == 0 ? NO_VIOLATIONS_DETECTED : return (methodsWithErrors.length == 0 ? NO_VIOLATIONS_DETECTED :
@ -197,7 +197,7 @@ public class SpringExtension implements BeforeAllCallback, AfterAllCallback, Tes
// re-validate the configuration for the same test class multiple times. // re-validate the configuration for the same test class multiple times.
Store store = context.getStore(RECORD_APPLICATION_EVENTS_VALIDATION_NAMESPACE); Store store = context.getStore(RECORD_APPLICATION_EVENTS_VALIDATION_NAMESPACE);
String errorMessage = store.getOrComputeIfAbsent(context.getRequiredTestClass(), testClass -> { String errorMessage = store.computeIfAbsent(context.getRequiredTestClass(), testClass -> {
boolean recording = TestContextAnnotationUtils.hasAnnotation(testClass, RecordApplicationEvents.class); boolean recording = TestContextAnnotationUtils.hasAnnotation(testClass, RecordApplicationEvents.class);
if (!recording) { if (!recording) {
return NO_VIOLATIONS_DETECTED; return NO_VIOLATIONS_DETECTED;
@ -358,7 +358,7 @@ public class SpringExtension implements BeforeAllCallback, AfterAllCallback, Tes
Assert.notNull(context, "ExtensionContext must not be null"); Assert.notNull(context, "ExtensionContext must not be null");
Class<?> testClass = context.getRequiredTestClass(); Class<?> testClass = context.getRequiredTestClass();
Store store = getStore(context); Store store = getStore(context);
return store.getOrComputeIfAbsent(testClass, TestContextManager::new, TestContextManager.class); return store.computeIfAbsent(testClass, TestContextManager::new, TestContextManager.class);
} }
private static Store getStore(ExtensionContext context) { private static Store getStore(ExtensionContext context) {
@ -372,7 +372,6 @@ public class SpringExtension implements BeforeAllCallback, AfterAllCallback, Tes
* the supplied {@link TestContextManager}. * the supplied {@link TestContextManager}.
* @since 6.1 * @since 6.1
*/ */
@SuppressWarnings("NullAway") // org.junit.jupiter.api.extension.ExecutableInvoker is not null marked
private static void registerMethodInvoker(TestContextManager testContextManager, ExtensionContext context) { private static void registerMethodInvoker(TestContextManager testContextManager, ExtensionContext context) {
testContextManager.getTestContext().setMethodInvoker(context.getExecutableInvoker()::invoke); testContextManager.getTestContext().setMethodInvoker(context.getExecutableInvoker()::invoke);
} }

View File

@ -56,7 +56,7 @@ import org.springframework.test.context.aot.samples.basic.DisabledInAotRuntimeMe
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.platform.engine.discovery.ClassNameFilter.includeClassNamePatterns; import static org.junit.platform.engine.discovery.ClassNameFilter.includeClassNamePatterns;
import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClasses;
import static org.junit.platform.launcher.TagFilter.excludeTags; import static org.junit.platform.launcher.TagFilter.excludeTags;
/** /**
@ -205,11 +205,11 @@ class AotIntegrationTests extends AbstractAotTests {
try { try {
System.setProperty(AotDetector.AOT_ENABLED, "true"); System.setProperty(AotDetector.AOT_ENABLED, "true");
LauncherDiscoveryRequestBuilder builder = LauncherDiscoveryRequestBuilder.request() LauncherDiscoveryRequest request = LauncherDiscoveryRequestBuilder.request()
.selectors(selectClasses(testClasses))
.filters(includeClassNamePatterns(".*Tests?$")) .filters(includeClassNamePatterns(".*Tests?$"))
.filters(excludeTags("failing-test-case")); .filters(excludeTags("failing-test-case"))
testClasses.forEach(testClass -> builder.selectors(selectClass(testClass))); .build();
LauncherDiscoveryRequest request = builder.build();
SummaryGeneratingListener listener = new SummaryGeneratingListener(); SummaryGeneratingListener listener = new SummaryGeneratingListener();
LauncherFactory.create().execute(request, listener); LauncherFactory.create().execute(request, listener);
TestExecutionSummary summary = listener.getSummary(); TestExecutionSummary summary = listener.getSummary();

View File

@ -31,7 +31,7 @@ import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
import org.springframework.test.context.support.DependencyInjectionTestExecutionListener; import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClasses;
import static org.springframework.test.context.CacheAwareContextLoaderDelegate.CONTEXT_FAILURE_THRESHOLD_PROPERTY_NAME; import static org.springframework.test.context.CacheAwareContextLoaderDelegate.CONTEXT_FAILURE_THRESHOLD_PROPERTY_NAME;
import static org.springframework.test.context.CacheAwareContextLoaderDelegate.DEFAULT_CONTEXT_FAILURE_THRESHOLD; import static org.springframework.test.context.CacheAwareContextLoaderDelegate.DEFAULT_CONTEXT_FAILURE_THRESHOLD;
import static org.springframework.test.context.cache.ContextCacheTestUtils.assertContextCacheStatistics; import static org.springframework.test.context.cache.ContextCacheTestUtils.assertContextCacheStatistics;
@ -85,14 +85,14 @@ class ContextFailureThresholdTests {
} }
private static void runTests() { private static void runTests() {
EngineTestKit.engine("junit-jupiter")// EngineTestKit.engine("junit-jupiter")
.selectors(// .selectors(selectClasses(
selectClass(PassingTestCase.class), // 3 passing PassingTestCase.class, // 3 passing
selectClass(FailingConfigTestCase.class), // 3 failing FailingConfigTestCase.class, // 3 failing
selectClass(SharedFailingConfigTestCase.class) // 3 failing SharedFailingConfigTestCase.class // 3 failing
)// ))
.execute()// .execute()
.testEvents()// .testEvents()
.assertStatistics(stats -> stats.started(9).succeeded(3).failed(6)); .assertStatistics(stats -> stats.started(9).succeeded(3).failed(6));
assertContextCacheStatistics(1, 2, (1 + 3 + 3)); assertContextCacheStatistics(1, 2, (1 + 3 + 3));
} }

View File

@ -16,8 +16,6 @@
package org.springframework.test.context.cache; package org.springframework.test.context.cache;
import java.util.Arrays;
import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.ClassOrderer; import org.junit.jupiter.api.ClassOrderer;
@ -25,8 +23,6 @@ import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Order; import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestClassOrder; import org.junit.jupiter.api.TestClassOrder;
import org.junit.platform.engine.discovery.ClassSelector;
import org.junit.platform.engine.discovery.DiscoverySelectors;
import org.junit.platform.testkit.engine.EngineTestKit; import org.junit.platform.testkit.engine.EngineTestKit;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
@ -38,6 +34,7 @@ import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClasses;
import static org.springframework.test.context.NestedTestConfiguration.EnclosingConfiguration.INHERIT; import static org.springframework.test.context.NestedTestConfiguration.EnclosingConfiguration.INHERIT;
import static org.springframework.test.context.NestedTestConfiguration.EnclosingConfiguration.OVERRIDE; import static org.springframework.test.context.NestedTestConfiguration.EnclosingConfiguration.OVERRIDE;
@ -209,10 +206,6 @@ class UnusedContextsIntegrationTests {
.assertStatistics(stats -> stats.started(expectedTestCount).succeeded(expectedTestCount)); .assertStatistics(stats -> stats.started(expectedTestCount).succeeded(expectedTestCount));
} }
private static ClassSelector[] selectClasses(Class<?>... classes) {
return Arrays.stream(classes).map(DiscoverySelectors::selectClass).toArray(ClassSelector[]::new);
}
@SpringJUnitConfig(EventTracker.class) @SpringJUnitConfig(EventTracker.class)
@ContextCustomizerFactories(DisplayNameCustomizerFactory.class) @ContextCustomizerFactories(DisplayNameCustomizerFactory.class)

View File

@ -40,7 +40,7 @@ import org.springframework.test.context.event.annotation.PrepareTestInstance;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClasses;
/** /**
* Tests for the {@link EventPublishingTestExecutionListener} which verify that * Tests for the {@link EventPublishingTestExecutionListener} which verify that
@ -65,7 +65,7 @@ class EagerTestExecutionEventPublishingTests {
@Test @Test
void beforeTestClassEventIsNotPublishedByDefaultForFirstTestClass() { void beforeTestClassEventIsNotPublishedByDefaultForFirstTestClass() {
EngineTestKit.engine("junit-jupiter")// EngineTestKit.engine("junit-jupiter")//
.selectors(selectClass(LazyTestCase1.class), selectClass(LazyTestCase2.class))// .selectors(selectClasses(LazyTestCase1.class, LazyTestCase2.class))//
.execute()// .execute()//
.testEvents()// .testEvents()//
.assertStatistics(stats -> stats.started(2).succeeded(2).failed(0)); .assertStatistics(stats -> stats.started(2).succeeded(2).failed(0));
@ -93,7 +93,7 @@ class EagerTestExecutionEventPublishingTests {
@Test @Test
void beforeTestClassEventIsPublishedForAllTestClassesIfCustomListenerEagerlyLoadsContext() { void beforeTestClassEventIsPublishedForAllTestClassesIfCustomListenerEagerlyLoadsContext() {
EngineTestKit.engine("junit-jupiter")// EngineTestKit.engine("junit-jupiter")//
.selectors(selectClass(EagerTestCase1.class), selectClass(EagerTestCase2.class))// .selectors(selectClasses(EagerTestCase1.class, EagerTestCase2.class))//
.execute()// .execute()//
.testEvents()// .testEvents()//
.assertStatistics(stats -> stats.started(2).succeeded(2).failed(0)); .assertStatistics(stats -> stats.started(2).succeeded(2).failed(0));

View File

@ -29,7 +29,7 @@ import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.context.junit.jupiter.SpringExtension;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass; import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClasses;
/** /**
* Test suite to investigate claims raised in * Test suite to investigate claims raised in
@ -66,12 +66,7 @@ class GeneratedDatabaseNamesTests {
@Test @Test
void runTestsWithGeneratedDatabaseNames() { void runTestsWithGeneratedDatabaseNames() {
EngineTestKit.engine("junit-jupiter") EngineTestKit.engine("junit-jupiter")
.selectors( .selectors(selectClasses(TestClass1A.class, TestClass1B.class, TestClass2A.class, TestClass2B.class))
selectClass(TestClass1A.class),
selectClass(TestClass1B.class),
selectClass(TestClass2A.class),
selectClass(TestClass2B.class)
)
.execute() .execute()
.testEvents() .testEvents()
.assertStatistics(stats -> stats.started(4).succeeded(4).failed(0)); .assertStatistics(stats -> stats.started(4).succeeded(4).failed(0));

View File

@ -112,7 +112,7 @@ class DisabledIfConditionTests {
Class<?> testClass = SpringTestCase.class; Class<?> testClass = SpringTestCase.class;
Method method = ReflectionUtils.findMethod(getClass(), methodName); Method method = ReflectionUtils.findMethod(getClass(), methodName);
Store store = mock(); Store store = mock();
given(store.getOrComputeIfAbsent(any(), any(), any())).willReturn(new TestContextManager(testClass)); given(store.computeIfAbsent(any(), any(), any())).willReturn(new TestContextManager(testClass));
ExtensionContext extensionContext = mock(); ExtensionContext extensionContext = mock();
given(extensionContext.getTestClass()).willReturn(Optional.of(testClass)); given(extensionContext.getTestClass()).willReturn(Optional.of(testClass));

View File

@ -55,7 +55,7 @@ class GzipSupport implements ParameterResolver {
@Override @Override
public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) { public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) {
return getStore(extensionContext).getOrComputeIfAbsent(GzippedFiles.class); return getStore(extensionContext).computeIfAbsent(GzippedFiles.class);
} }
private Store getStore(ExtensionContext extensionContext) { private Store getStore(ExtensionContext extensionContext) {

View File

@ -55,7 +55,7 @@ class GzipSupport implements ParameterResolver {
@Override @Override
public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) { public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) {
return getStore(extensionContext).getOrComputeIfAbsent(GzippedFiles.class); return getStore(extensionContext).computeIfAbsent(GzippedFiles.class);
} }
private Store getStore(ExtensionContext extensionContext) { private Store getStore(ExtensionContext extensionContext) {