diff --git a/spring-test/src/main/java/org/springframework/test/context/aot/TestContextAotGenerator.java b/spring-test/src/main/java/org/springframework/test/context/aot/TestContextAotGenerator.java index 0f0dc0d191..eff97bda8b 100644 --- a/spring-test/src/main/java/org/springframework/test/context/aot/TestContextAotGenerator.java +++ b/spring-test/src/main/java/org/springframework/test/context/aot/TestContextAotGenerator.java @@ -17,6 +17,7 @@ package org.springframework.test.context.aot; import java.util.Arrays; +import java.util.Collections; import java.util.concurrent.atomic.AtomicInteger; import java.util.stream.Stream; @@ -31,6 +32,7 @@ import org.springframework.aot.generate.GenerationContext; import org.springframework.aot.hint.ReflectionHints; import org.springframework.aot.hint.RuntimeHints; import org.springframework.aot.hint.TypeReference; +import org.springframework.beans.factory.aot.AotServices; import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContextInitializer; import org.springframework.context.aot.ApplicationContextAotGenerator; @@ -67,6 +69,8 @@ public class TestContextAotGenerator { private final ApplicationContextAotGenerator aotGenerator = new ApplicationContextAotGenerator(); + private final AotServices testRuntimeHintsRegistrars; + private final AtomicInteger sequence = new AtomicInteger(); private final GeneratedFiles generatedFiles; @@ -90,6 +94,7 @@ public class TestContextAotGenerator { * @param runtimeHints the {@code RuntimeHints} to use */ public TestContextAotGenerator(GeneratedFiles generatedFiles, RuntimeHints runtimeHints) { + this.testRuntimeHintsRegistrars = AotServices.factories().load(TestRuntimeHintsRegistrar.class); this.generatedFiles = generatedFiles; this.runtimeHints = runtimeHints; } @@ -121,6 +126,9 @@ public class TestContextAotGenerator { testClasses.stream().map(Class::getName).toList())); registerHintsForMergedConfig(mergedConfig); try { + this.testRuntimeHintsRegistrars.forEach(registrar -> registrar.registerHints(this.runtimeHints, + mergedConfig, Collections.unmodifiableList(testClasses), getClass().getClassLoader())); + // Use first test class discovered for a given unique MergedContextConfiguration. Class testClass = testClasses.get(0); DefaultGenerationContext generationContext = createGenerationContext(testClass); diff --git a/spring-test/src/main/java/org/springframework/test/context/aot/TestRuntimeHintsRegistrar.java b/spring-test/src/main/java/org/springframework/test/context/aot/TestRuntimeHintsRegistrar.java new file mode 100644 index 0000000000..49b87b85f1 --- /dev/null +++ b/spring-test/src/main/java/org/springframework/test/context/aot/TestRuntimeHintsRegistrar.java @@ -0,0 +1,57 @@ +/* + * Copyright 2002-2022 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.util.List; + +import org.springframework.aot.hint.RuntimeHints; +import org.springframework.test.context.MergedContextConfiguration; + +/** + * Contract for registering {@link RuntimeHints} for integration tests run with + * the Spring TestContext Framework based on the {@link ClassLoader} + * of the deployment unit. Implementations should, if possible, use the specified + * {@link ClassLoader} to determine if hints have to be contributed. + * + *

Implementations of this interface must be registered statically in + * {@code META-INF/spring/aot.factories} by using the fully qualified name of this + * interface as the key. A standard no-arg constructor is required for implementations. + * + *

This API serves as a companion to the core + * {@link org.springframework.aot.hint.RuntimeHintsRegistrar RuntimeHintsRegistrar} + * API. If you need to register global hints for testing support that are not + * specific to a particular test class or {@link MergedContextConfiguration}, favor + * implementing {@code RuntimeHintsRegistrar} over this API. + * + * @author Sam Brannen + * @since 6.0 + * @see org.springframework.aot.hint.RuntimeHintsRegistrar + */ +public interface TestRuntimeHintsRegistrar { + + /** + * Contribute hints to the given {@link RuntimeHints} instance. + * @param runtimeHints the {@code RuntimeHints} to use + * @param mergedConfig the merged context configuration to process + * @param testClasses the test classes that share the supplied merged context + * configuration + * @param classLoader the classloader to use + */ + void registerHints(RuntimeHints runtimeHints, MergedContextConfiguration mergedConfig, + List> testClasses, ClassLoader classLoader); + +}