From 00201a2e7826ee178d97a6c135a6d48268956a5d Mon Sep 17 00:00:00 2001 From: Vasily Pelikh <2010720+vpelikh@users.noreply.github.com> Date: Mon, 10 Aug 2026 14:58:02 +0300 Subject: [PATCH 1/2] Detect and verify JVM AOT cache recording during integration tests Introduce an AotCacheTestExecutionListener that is registered by default and activates automatically when the test JVM is started with AOT cache recording enabled via the JDK 25+ -XX:AOTCacheOutput= flag (injected by the Spring Boot Maven or Gradle plugins). When active, the listener validates the JDK version and the application class loader, eagerly loads the ApplicationContext so that context creation is captured as part of the training workload, warns if spring.context.exit=onRefresh is set, and verifies on JVM exit that the cache file was produced at the path specified by the -XX:AOTCacheOutput flag. Signed-off-by: Vasily Pelikh <2010720+vpelikh@users.noreply.github.com> --- .../ROOT/pages/integration/aot-cache.adoc | 51 ++++ .../testcontext-framework/tel-config.adoc | 3 + .../test/context/TestExecutionListener.java | 2 + .../aot/AotCacheTestExecutionListener.java | 256 ++++++++++++++++++ .../main/resources/META-INF/spring.factories | 3 +- .../AotCacheTestExecutionListenerTests.java | 196 ++++++++++++++ 6 files changed, 510 insertions(+), 1 deletion(-) create mode 100644 spring-test/src/main/java/org/springframework/test/context/aot/AotCacheTestExecutionListener.java create mode 100644 spring-test/src/test/java/org/springframework/test/context/aot/AotCacheTestExecutionListenerTests.java diff --git a/framework-docs/modules/ROOT/pages/integration/aot-cache.adoc b/framework-docs/modules/ROOT/pages/integration/aot-cache.adoc index 57d0aed17c16..32acc9d9fdcb 100644 --- a/framework-docs/modules/ROOT/pages/integration/aot-cache.adoc +++ b/framework-docs/modules/ROOT/pages/integration/aot-cache.adoc @@ -118,3 +118,54 @@ the cache, make sure that the following conditions are fulfilled when creating a - The timestamps of the JARs must be preserved. - When using the cache, the classpath must be the same as the one used to create it, in the same order. Additional JARs or directories can be specified *at the end* (but will not be cached). + +[[aot-cache-integration-tests]] +== Generating the cache from integration tests + +In addition to creating the AOT cache via a dedicated training run, you can also +generate the cache as a side effect of running integration tests. This is useful +when your test suite exercises a significant portion of the application's startup +and request-handling workflow, producing a more effective cache than a simple +`-Dspring.context.exit=onRefresh` run. The cache also stores method +profiling information, so exercising realistic code paths improves warmup behavior as well. + +Spring Framework provides the +`org.springframework.test.context.aot.AotCacheTestExecutionListener` for this purpose. +The listener is registered by default and activates automatically when the test JVM is +started with AOT cache recording enabled. When active, this listener: + +. Validates that the JDK supports AOT cache recording (JDK 25+). +. Eagerly loads the `ApplicationContext` so that context creation is part of the training workload. +. Warns when the `-Dspring.context.exit=onRefresh` flag is present, since it would + terminate the test JVM mid-run. +. Verifies the cache file was produced on JVM exit. + +To enable AOT cache recording from integration tests, the build tool (Maven or Gradle) +must pass the JVM flag that specifies the cache output path. By convention, the cache is +written to `aot-cache/application.aot` relative to the test working directory, which +matches the location detected by the Paketo Spring Boot buildpack and bundled into the +image by the Spring Boot build plugins: + +[source,bash,subs="verbatim,quotes"] +---- +-XX:AOTCacheOutput=aot-cache/application.aot +---- + +The listener does not set JVM flags itself; it only detects them. No additional Spring +configuration is required, since the JVM flags are the single source of truth for whether +recording is enabled and where the cache file is written. + +NOTE: The `-Dspring.context.exit=onRefresh` flag is *not* needed when generating the +cache from integration tests, because the test JVM exits normally at the end of the run. +If it is present, the listener logs a warning. + +For the AOT cache to work correctly, the application must: + +* Use the standard JDK class loader (not a custom class loader). +* Be deployed as an extracted JAR or with a standard classpath layout. + +On JVM exit, the listener verifies that the cache file was produced at the path specified +by the `-XX:AOTCacheOutput` flag and logs a warning if it is missing. + +TIP: The Maven/Gradle flag wiring for `-XX:AOTCacheOutput` is provided by the Spring Boot +Maven and Gradle plugins. Consult the Spring Boot documentation for build tool integration details. diff --git a/framework-docs/modules/ROOT/pages/testing/testcontext-framework/tel-config.adoc b/framework-docs/modules/ROOT/pages/testing/testcontext-framework/tel-config.adoc index 0b89b0672419..bf679690d47c 100644 --- a/framework-docs/modules/ROOT/pages/testing/testcontext-framework/tel-config.adoc +++ b/framework-docs/modules/ROOT/pages/testing/testcontext-framework/tel-config.adoc @@ -20,6 +20,9 @@ by default, exactly in the following order: "after" modes. * `CommonCachesTestExecutionListener`: Clears resource caches in the test's `ApplicationContext` if necessary. +* `AotCacheTestExecutionListener`: Coordinates JVM AOT cache recording during integration + tests. It activates automatically when the test JVM is started with AOT cache recording + flags (see xref:integration/aot-cache.adoc#aot-cache-integration-tests[Generating the cache from integration tests]). * `TransactionalTestExecutionListener`: Provides transactional test execution with default rollback semantics. * `SqlScriptsTestExecutionListener`: Runs SQL scripts configured by using the `@Sql` diff --git a/spring-test/src/main/java/org/springframework/test/context/TestExecutionListener.java b/spring-test/src/main/java/org/springframework/test/context/TestExecutionListener.java index 81327908d9f9..3c30e017d377 100644 --- a/spring-test/src/main/java/org/springframework/test/context/TestExecutionListener.java +++ b/spring-test/src/main/java/org/springframework/test/context/TestExecutionListener.java @@ -106,6 +106,8 @@ * DirtiesContextTestExecutionListener} *
  • {@link org.springframework.test.context.support.CommonCachesTestExecutionListener * CommonCachesTestExecutionListener}
  • + *
  • {@link org.springframework.test.context.aot.AotCacheTestExecutionListener + * AotCacheTestExecutionListener}
  • *
  • {@link org.springframework.test.context.transaction.TransactionalTestExecutionListener * TransactionalTestExecutionListener}
  • *
  • {@link org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener diff --git a/spring-test/src/main/java/org/springframework/test/context/aot/AotCacheTestExecutionListener.java b/spring-test/src/main/java/org/springframework/test/context/aot/AotCacheTestExecutionListener.java new file mode 100644 index 000000000000..d9a378320282 --- /dev/null +++ b/spring-test/src/main/java/org/springframework/test/context/aot/AotCacheTestExecutionListener.java @@ -0,0 +1,256 @@ +/* + * Copyright 2002-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.test.context.aot; + +import java.io.File; +import java.lang.management.ManagementFactory; +import java.util.List; +import java.util.concurrent.atomic.AtomicBoolean; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.jspecify.annotations.Nullable; + +import org.springframework.context.ApplicationContext; +import org.springframework.context.support.DefaultLifecycleProcessor; +import org.springframework.core.SpringProperties; +import org.springframework.test.context.TestContext; +import org.springframework.test.context.support.AbstractTestExecutionListener; + +/** + * {@code TestExecutionListener} that coordinates JVM AOT cache recording + * during integration tests, as proposed in + * issue #36774. + * + *

    This listener is registered by default and activates automatically when the test JVM + * is started with AOT cache recording enabled, that is with the JDK 25+ single-step + * {@code -XX:AOTCacheOutput=} flag. + * The flag injection itself is the responsibility of the build tooling used for the test + * run (for example, the Spring Boot Maven or Gradle plugins), since JVM flags can only be + * configured at startup. + * + *

    When active, this listener: + *

    + * + *

    Requires JDK 25 or later (JEP 514). + * + * @author Vasily Pelikh + * @since 7.1 + * @see JEP 483: Ahead-of-Time Class Loading & Linking + * @see JEP 514: Ahead-of-Time Command-Line Ergonomics + */ +public class AotCacheTestExecutionListener extends AbstractTestExecutionListener { + + /** + * The {@link #getOrder() order} value for this listener: {@value}. + * Ordered after {@link org.springframework.test.context.support.CommonCachesTestExecutionListener} + * and before {@link org.springframework.test.context.transaction.TransactionalTestExecutionListener}. + * @since 7.1 + */ + public static final int ORDER = 3006; + + private static final String AOT_CACHE_OUTPUT_FLAG_PREFIX = "-XX:AOTCacheOutput="; + + private static final Log logger = LogFactory.getLog(AotCacheTestExecutionListener.class); + + // Static state: at most one shutdown hook can be registered per JVM. In normal usage, the + // build tool passes a single -XX:AOTCacheOutput path for the entire test run, so one hook + // that verifies that path suffices. + private static final AtomicBoolean shutdownHookRegistered = new AtomicBoolean(); + + /** + * Returns {@value #ORDER}. + */ + @Override + public final int getOrder() { + return ORDER; + } + + @Override + public void beforeTestClass(TestContext testContext) throws Exception { + List jvmArguments = getInputArguments(); + if (!isAotRecordingEnabled(jvmArguments)) { + return; + } + logger.info("AOT cache recording is enabled. Preparing the training workload for test class [" + + testContext.getTestClass().getName() + "]."); + + validateJdkVersion(); + + // Access the ApplicationContext eagerly so that the training workload from context + // creation (bean instantiation, @PostConstruct callbacks, etc.) is captured by the + // JVM's AOT cache mechanism. + ApplicationContext context = testContext.getApplicationContext(); + validateClassLoader(context); + + warnIfExitOnRefresh(); + + String aotCacheOutput = findAotCacheOutput(jvmArguments); + if (aotCacheOutput != null) { + logger.info("Expected AOT cache output path: " + aotCacheOutput); + registerCacheOutputVerification(aotCacheOutput); + } + } + + /** + * Validate that the JDK version supports AOT cache recording. + * @throws IllegalStateException if the JDK version is unsupported + */ + protected void validateJdkVersion() { + int currentVersion = Runtime.version().feature(); + int requiredVersion = getRequiredJavaFeatureVersion(); + if (currentVersion < requiredVersion) { + throw new IllegalStateException(String.format( + "AOT cache recording requires JDK %d or later (JEP 514). " + + "Current JDK version: %d", requiredVersion, currentVersion)); + } + } + + /** + * Validate that the given application context uses a standard JDK class loader. + * @param context the application context + */ + protected void validateClassLoader(ApplicationContext context) { + ClassLoader classLoader = context.getClassLoader(); + if (classLoader != null && !isStandardClassLoader(classLoader)) { + logger.warn(String.format(""" + The ApplicationContext class loader [%s] is not a standard JDK class loader. + AOT cache only caches classes loaded by JDK built-in class loaders (JEP 483). + Use an extracted JAR layout with the standard class loader (for example, \ + Spring Boot's executable JAR unpacking) for the cache to be effective.""", + classLoader.getClass().getName())); + } + } + + /** + * Determine whether the {@code -Dspring.context.exit=onRefresh} flag is configured. + * @return {@code true} if the flag is set to {@code onRefresh} + */ + protected boolean isExitOnRefreshConfigured() { + return "onRefresh".equalsIgnoreCase(SpringProperties.getProperty(DefaultLifecycleProcessor.EXIT_PROPERTY_NAME)); + } + + private void warnIfExitOnRefresh() { + if (isExitOnRefreshConfigured()) { + logger.warn("The '" + DefaultLifecycleProcessor.EXIT_PROPERTY_NAME + "=onRefresh' property is set. " + + "This terminates the JVM when the ApplicationContext refreshes and is not compatible " + + "with generating an AOT cache from integration tests. Remove it from the test JVM arguments."); + } + } + + /** + * Return the minimum JDK feature version required for AOT cache recording. + *

    JDK 25 introduced the single-step {@code -XX:AOTCacheOutput} workflow (JEP 514). + * Override in tests to simulate unsupported JDK versions. + * @return the required JDK feature version (default: 25) + */ + protected int getRequiredJavaFeatureVersion() { + return 25; + } + + /** + * Determine whether the given class loader is a standard JDK class loader + * suitable for AOT cache recording. + *

    Leyden only caches classes loaded by JDK built-in class loaders + * (such as {@code jdk.internal.loader.BuiltinClassLoader} and its + * {@code AppClassLoader} / {@code PlatformClassLoader} subclasses). Custom + * class loaders (for example, Spring Boot's {@code LaunchedURLClassLoader}) + * prevent classes from being cached. + * @param classLoader the class loader to check (never {@code null}) + * @return {@code true} if the class loader is a standard JDK class loader + */ + protected boolean isStandardClassLoader(ClassLoader classLoader) { + String className = classLoader.getClass().getName(); + return className.startsWith("jdk.internal.loader."); + } + + /** + * Determine whether the given JVM arguments enable AOT cache recording via the JDK 25+ + * single-step {@code -XX:AOTCacheOutput} flag. + * @param jvmArguments the JVM command-line arguments + * @return {@code true} if AOT cache recording is enabled + */ + static boolean isAotRecordingEnabled(List jvmArguments) { + for (String argument : jvmArguments) { + if (argument.startsWith(AOT_CACHE_OUTPUT_FLAG_PREFIX)) { + return true; + } + } + return false; + } + + /** + * Return the value of the {@code -XX:AOTCacheOutput} JVM flag, or {@code null} if + * the flag is not present in the given JVM arguments. + * @param jvmArguments the JVM command-line arguments + * @return the AOT cache output path, or {@code null} + */ + static @Nullable String findAotCacheOutput(List jvmArguments) { + for (String argument : jvmArguments) { + if (argument.startsWith(AOT_CACHE_OUTPUT_FLAG_PREFIX)) { + return argument.substring(AOT_CACHE_OUTPUT_FLAG_PREFIX.length()); + } + } + return null; + } + + /** + * Return the JVM command-line arguments, excluding the arguments passed to the + * {@code main} method. + *

    Exposed for testing purposes. + * @return the JVM command-line arguments + */ + protected List getInputArguments() { + return ManagementFactory.getRuntimeMXBean().getInputArguments(); + } + + private void registerCacheOutputVerification(String outputPath) { + if (shutdownHookRegistered.compareAndSet(false, true)) { + Runtime.getRuntime().addShutdownHook(new Thread(() -> verifyCacheOutput(outputPath))); + } + } + + /** + * Verify that the AOT cache file was created at the given output path. + * @param outputPath the expected AOT cache output path + * @return {@code true} if the cache file exists + */ + boolean verifyCacheOutput(String outputPath) { + File cacheFile = new File(outputPath); + if (cacheFile.exists()) { + logger.info("AOT cache file created successfully: " + cacheFile.getAbsolutePath() + + " (" + cacheFile.length() + " bytes)"); + return true; + } + else { + logger.warn("AOT cache file was NOT created at: " + cacheFile.getAbsolutePath() + + ". Verify that the JVM was started with '-XX:AOTCacheOutput=' (JDK 25+) " + + "and that the application uses the standard JDK class loader with an extracted JAR layout."); + return false; + } + } + +} diff --git a/spring-test/src/main/resources/META-INF/spring.factories b/spring-test/src/main/resources/META-INF/spring.factories index 344b3ecb2074..b9b89435651e 100644 --- a/spring-test/src/main/resources/META-INF/spring.factories +++ b/spring-test/src/main/resources/META-INF/spring.factories @@ -12,7 +12,8 @@ org.springframework.test.context.TestExecutionListener = \ org.springframework.test.context.transaction.TransactionalTestExecutionListener,\ org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener,\ org.springframework.test.context.event.EventPublishingTestExecutionListener,\ - org.springframework.test.context.bean.override.mockito.MockitoResetTestExecutionListener + org.springframework.test.context.bean.override.mockito.MockitoResetTestExecutionListener,\ + org.springframework.test.context.aot.AotCacheTestExecutionListener # Default ContextCustomizerFactory implementations for the Spring TestContext Framework # diff --git a/spring-test/src/test/java/org/springframework/test/context/aot/AotCacheTestExecutionListenerTests.java b/spring-test/src/test/java/org/springframework/test/context/aot/AotCacheTestExecutionListenerTests.java new file mode 100644 index 000000000000..a246b108163d --- /dev/null +++ b/spring-test/src/test/java/org/springframework/test/context/aot/AotCacheTestExecutionListenerTests.java @@ -0,0 +1,196 @@ +/* + * Copyright 2002-present the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.test.context.aot; + +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.List; + +import org.jspecify.annotations.NonNull; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; + +import org.springframework.context.ApplicationContext; +import org.springframework.context.support.DefaultLifecycleProcessor; +import org.springframework.core.SpringProperties; +import org.springframework.test.context.TestContext; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatIllegalStateException; +import static org.mockito.BDDMockito.given; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; + +/** + * Tests for {@link AotCacheTestExecutionListener}. + * + * @author Vasily Pelikh + * @since 7.1 + */ +class AotCacheTestExecutionListenerTests { + + private final AotCacheTestExecutionListener listener = new AotCacheTestExecutionListener(); + + @AfterEach + void clearProperties() { + SpringProperties.setProperty(DefaultLifecycleProcessor.EXIT_PROPERTY_NAME, null); + } + + @Test + void orderValue() { + assertThat(listener.getOrder()).isEqualTo(3006); + } + + @Test + void beforeTestClassWhenRecordingIsNotEnabled() throws Exception { + TestContext testContext = mock(); + listener.beforeTestClass(testContext); + verify(testContext, never()).getApplicationContext(); + } + + @Test + void beforeTestClassWhenAotCacheOutputFlagIsPresent() throws Exception { + ApplicationContext applicationContext = mock(); + TestContext testContext = mock(); + given((Class) testContext.getTestClass()).willReturn((Class) AotCacheTestExecutionListenerTests.class); + given(testContext.getApplicationContext()).willReturn(applicationContext); + + AotCacheTestExecutionListener recordingListener = listenerWithArgs("-XX:AOTCacheOutput=build/app.aot"); + recordingListener.beforeTestClass(testContext); + + verify(testContext).getApplicationContext(); + } + + @Test + void beforeTestClassWhenJdkVersionIsUnsupported() { + AotCacheTestExecutionListener unsupportedListener = new AotCacheTestExecutionListener() { + @Override + protected List getInputArguments() { + return List.of("-XX:AOTCacheOutput=build/app.aot"); + } + + @Override + protected int getRequiredJavaFeatureVersion() { + return 9999; + } + }; + TestContext testContext = mock(); + given((Class) testContext.getTestClass()).willReturn((Class) AotCacheTestExecutionListenerTests.class); + + assertThatIllegalStateException() + .isThrownBy(() -> unsupportedListener.beforeTestClass(testContext)) + .withMessageContaining("JDK"); + verify(testContext, never()).getApplicationContext(); + } + + @Test + void beforeTestClassWhenClassLoaderIsNotStandard() throws Exception { + AotCacheTestExecutionListener warnListener = new AotCacheTestExecutionListener() { + @Override + protected List getInputArguments() { + return List.of("-XX:AOTCacheOutput=build/app.aot"); + } + + @Override + protected boolean isStandardClassLoader(ClassLoader classLoader) { + return false; + } + }; + ApplicationContext applicationContext = mock(); + given(applicationContext.getClassLoader()).willReturn(AotCacheTestExecutionListenerTests.class.getClassLoader()); + TestContext testContext = mock(); + given((Class) testContext.getTestClass()).willReturn((Class) AotCacheTestExecutionListenerTests.class); + given(testContext.getApplicationContext()).willReturn(applicationContext); + + warnListener.beforeTestClass(testContext); + + verify(testContext).getApplicationContext(); + } + + @Test + void isExitOnRefreshConfiguredWhenPropertyIsSet() { + SpringProperties.setProperty(DefaultLifecycleProcessor.EXIT_PROPERTY_NAME, "onRefresh"); + assertThat(listener.isExitOnRefreshConfigured()).isTrue(); + } + + @Test + void isExitOnRefreshConfiguredWhenPropertyIsNotSet() { + assertThat(listener.isExitOnRefreshConfigured()).isFalse(); + } + + @Test + void isAotRecordingEnabledWhenAotCacheOutputFlagIsPresent() { + assertThat(AotCacheTestExecutionListener.isAotRecordingEnabled( + List.of("-Xmx512m", "-XX:AOTCacheOutput=build/app.aot", "-jar", "app.jar"))).isTrue(); + } + + @Test + void isAotRecordingEnabledWhenAotModeRecordFlagIsPresentIsNotSupported() { + // JDK 24 two-step record mode is not supported; only the JDK 25+ single-step flag + assertThat(AotCacheTestExecutionListener.isAotRecordingEnabled( + List.of("-XX:AOTMode=record", "-XX:AOTConfiguration=build/app.aotconf"))).isFalse(); + } + + @Test + void isAotRecordingEnabledWhenNoRecordingFlagIsPresent() { + assertThat(AotCacheTestExecutionListener.isAotRecordingEnabled( + List.of("-Xmx512m", "-jar", "app.jar"))).isFalse(); + } + + @Test + void isAotRecordingEnabledWhenAotModeCreateFlagIsPresent() { + // -XX:AOTMode=create alone does not record a training run + assertThat(AotCacheTestExecutionListener.isAotRecordingEnabled( + List.of("-XX:AOTMode=create", "-XX:AOTCache=build/app.aot"))).isFalse(); + } + + @Test + void findAotCacheOutputWhenFlagIsPresent() { + assertThat(AotCacheTestExecutionListener.findAotCacheOutput( + List.of("-Xmx512m", "-XX:AOTCacheOutput=build/app.aot"))).isEqualTo("build/app.aot"); + } + + @Test + void findAotCacheOutputWhenFlagIsAbsent() { + assertThat(AotCacheTestExecutionListener.findAotCacheOutput(List.of("-Xmx512m"))).isNull(); + } + + @Test + void verifyCacheOutputWhenFileExists(@TempDir Path tempDir) throws Exception { + Path cacheFile = tempDir.resolve("app.aot"); + Files.writeString(cacheFile, "test"); + assertThat(listener.verifyCacheOutput(cacheFile.toString())).isTrue(); + } + + @Test + void verifyCacheOutputWhenFileDoesNotExist() { + assertThat(listener.verifyCacheOutput("does-not-exist.aot")).isFalse(); + } + + private AotCacheTestExecutionListener listenerWithArgs(String... args) { + List inputArgs = List.of(args); + return new AotCacheTestExecutionListener() { + @Override + protected List getInputArguments() { + return inputArgs; + } + }; + } + +} From 57d0ee08dcfbebdc4320cc3ec62266d901c1db06 Mon Sep 17 00:00:00 2001 From: Vasily Pelikh <2010720+vpelikh@users.noreply.github.com> Date: Wed, 12 Aug 2026 17:25:42 +0300 Subject: [PATCH 2/2] Fix default test-execution-listener assertions and unused import Update TestExecutionListenersTests to include the new AotCacheTestExecutionListener in the expected default listener lists, and remove an unused jspecify NonNull import from AotCacheTestExecutionListenerTests that failed checkstyle. Signed-off-by: Vasily Pelikh <2010720+vpelikh@users.noreply.github.com> --- .../test/context/TestExecutionListenersTests.java | 5 +++++ .../test/context/aot/AotCacheTestExecutionListenerTests.java | 1 - 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/spring-test/src/test/java/org/springframework/test/context/TestExecutionListenersTests.java b/spring-test/src/test/java/org/springframework/test/context/TestExecutionListenersTests.java index 36f31894c5e6..f6f96ee5cf00 100644 --- a/spring-test/src/test/java/org/springframework/test/context/TestExecutionListenersTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/TestExecutionListenersTests.java @@ -25,6 +25,7 @@ import org.springframework.core.Ordered; import org.springframework.core.annotation.AliasFor; import org.springframework.core.annotation.AnnotationConfigurationException; +import org.springframework.test.context.aot.AotCacheTestExecutionListener; import org.springframework.test.context.bean.override.BeanOverrideTestExecutionListener; import org.springframework.test.context.bean.override.mockito.MockitoResetTestExecutionListener; import org.springframework.test.context.event.ApplicationEventsTestExecutionListener; @@ -73,6 +74,7 @@ void defaultListeners() { MICROMETER_LISTENER_CLASS,// DirtiesContextTestExecutionListener.class,// CommonCachesTestExecutionListener.class, // + AotCacheTestExecutionListener.class,// TransactionalTestExecutionListener.class,// SqlScriptsTestExecutionListener.class,// EventPublishingTestExecutionListener.class,// @@ -96,6 +98,7 @@ void defaultListenersMergedWithCustomListenerPrepended() { MICROMETER_LISTENER_CLASS,// DirtiesContextTestExecutionListener.class,// CommonCachesTestExecutionListener.class, // + AotCacheTestExecutionListener.class,// TransactionalTestExecutionListener.class,// SqlScriptsTestExecutionListener.class,// EventPublishingTestExecutionListener.class,// @@ -118,6 +121,7 @@ void defaultListenersMergedWithCustomListenerAppended() { MICROMETER_LISTENER_CLASS,// DirtiesContextTestExecutionListener.class,// CommonCachesTestExecutionListener.class, // + AotCacheTestExecutionListener.class, TransactionalTestExecutionListener.class, SqlScriptsTestExecutionListener.class,// EventPublishingTestExecutionListener.class,// @@ -142,6 +146,7 @@ void defaultListenersMergedWithCustomListenerInserted() { MICROMETER_LISTENER_CLASS,// DirtiesContextTestExecutionListener.class,// CommonCachesTestExecutionListener.class, // + AotCacheTestExecutionListener.class,// TransactionalTestExecutionListener.class,// SqlScriptsTestExecutionListener.class,// EventPublishingTestExecutionListener.class,// diff --git a/spring-test/src/test/java/org/springframework/test/context/aot/AotCacheTestExecutionListenerTests.java b/spring-test/src/test/java/org/springframework/test/context/aot/AotCacheTestExecutionListenerTests.java index a246b108163d..25fc1d9892e3 100644 --- a/spring-test/src/test/java/org/springframework/test/context/aot/AotCacheTestExecutionListenerTests.java +++ b/spring-test/src/test/java/org/springframework/test/context/aot/AotCacheTestExecutionListenerTests.java @@ -20,7 +20,6 @@ import java.nio.file.Path; import java.util.List; -import org.jspecify.annotations.NonNull; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir;