Supply RuntimeHints to an AotContextLoader
This commit introduces a new loadContextForAotProcessing(...) variant in AotContextLoader which accepts a RuntimeHints argument. This new method is an interface default method which delegates to the existing loadContextForAotProcessing(MergedContextConfiguration) variant for backward compatibility. In addition, the original loadContextForAotProcessing(...) variant is now deprecated and has been converted to an interface default method which throws an UnsupportedOperationException. Note, however, that the framework now only invokes the new loadContextForAotProcessing(...) variant within TestContextAotGenerator. Closes gh-34513
This commit is contained in:
parent
adfeba23e0
commit
e421104cf3
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2025 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.
|
||||
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
package org.springframework.test.context.aot;
|
||||
|
||||
import org.springframework.aot.hint.RuntimeHints;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextInitializer;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
|
|
@ -25,9 +26,9 @@ import org.springframework.test.context.SmartContextLoader;
|
|||
|
||||
/**
|
||||
* Strategy interface for loading an {@link ApplicationContext} for build-time
|
||||
* {@linkplain #loadContextForAotProcessing AOT processing} as well as run-time
|
||||
* {@linkplain #loadContextForAotRuntime AOT execution} for an integration test
|
||||
* managed by the Spring TestContext Framework.
|
||||
* {@linkplain #loadContextForAotProcessing(MergedContextConfiguration, RuntimeHints)
|
||||
* AOT processing} as well as run-time {@linkplain #loadContextForAotRuntime
|
||||
* AOT execution} for an integration test managed by the Spring TestContext Framework.
|
||||
*
|
||||
* <p>{@code AotContextLoader} is an extension of the {@link SmartContextLoader}
|
||||
* SPI that allows a context loader to optionally provide ahead-of-time (AOT)
|
||||
|
|
@ -42,6 +43,30 @@ import org.springframework.test.context.SmartContextLoader;
|
|||
*/
|
||||
public interface AotContextLoader extends SmartContextLoader {
|
||||
|
||||
/**
|
||||
* Load a new {@link ApplicationContext} for AOT build-time processing based
|
||||
* on the supplied {@link MergedContextConfiguration}, configure the context,
|
||||
* and return the context.
|
||||
* <p>The default implementation of this method throws an
|
||||
* {@link UnsupportedOperationException}. Note, however, that the framework
|
||||
* invokes {@link #loadContextForAotProcessing(MergedContextConfiguration, RuntimeHints)}
|
||||
* as of Spring Framework 6.2.4.
|
||||
* @param mergedConfig the merged context configuration to use to load the
|
||||
* application context
|
||||
* @return a new {@code GenericApplicationContext}
|
||||
* @throws ContextLoadException if context loading failed
|
||||
* @see #loadContextForAotProcessing(MergedContextConfiguration, RuntimeHints)
|
||||
* @see #loadContextForAotRuntime(MergedContextConfiguration, ApplicationContextInitializer)
|
||||
* @deprecated as of Spring Framework 6.2.4, in favor of
|
||||
* {@link #loadContextForAotProcessing(MergedContextConfiguration, RuntimeHints)};
|
||||
* to be removed in Spring Framework 8.0
|
||||
*/
|
||||
@Deprecated(since = "6.2.4", forRemoval = true)
|
||||
default ApplicationContext loadContextForAotProcessing(MergedContextConfiguration mergedConfig) throws Exception {
|
||||
throw new UnsupportedOperationException(
|
||||
"Invoke loadContextForAotProcessing(MergedContextConfiguration, RuntimeHints) instead");
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a new {@link ApplicationContext} for AOT build-time processing based
|
||||
* on the supplied {@link MergedContextConfiguration}, configure the context,
|
||||
|
|
@ -65,13 +90,23 @@ public interface AotContextLoader extends SmartContextLoader {
|
|||
* throw new ContextLoadException(context, ex);
|
||||
* }
|
||||
* </pre>
|
||||
* <p>For backward compatibility, the default implementation of this method
|
||||
* delegates to {@link #loadContextForAotProcessing(MergedContextConfiguration)}.
|
||||
* Note, however, that the framework only invokes this method as of Spring
|
||||
* Framework 6.2.4.
|
||||
* @param mergedConfig the merged context configuration to use to load the
|
||||
* application context
|
||||
* @param runtimeHints the runtime hints
|
||||
* @return a new {@code GenericApplicationContext}
|
||||
* @throws ContextLoadException if context loading failed
|
||||
* @since 6.2.4
|
||||
* @see #loadContextForAotRuntime(MergedContextConfiguration, ApplicationContextInitializer)
|
||||
*/
|
||||
ApplicationContext loadContextForAotProcessing(MergedContextConfiguration mergedConfig) throws Exception;
|
||||
default ApplicationContext loadContextForAotProcessing(MergedContextConfiguration mergedConfig,
|
||||
RuntimeHints runtimeHints) throws Exception {
|
||||
|
||||
return loadContextForAotProcessing(mergedConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a new {@link ApplicationContext} for AOT run-time execution based on
|
||||
|
|
@ -98,7 +133,7 @@ public interface AotContextLoader extends SmartContextLoader {
|
|||
* be applied to the context in order to recreate bean definitions
|
||||
* @return a new {@code GenericApplicationContext}
|
||||
* @throws ContextLoadException if context loading failed
|
||||
* @see #loadContextForAotProcessing(MergedContextConfiguration)
|
||||
* @see #loadContextForAotProcessing(MergedContextConfiguration, RuntimeHints)
|
||||
*/
|
||||
ApplicationContext loadContextForAotRuntime(MergedContextConfiguration mergedConfig,
|
||||
ApplicationContextInitializer<ConfigurableApplicationContext> initializer) throws Exception;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 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.
|
||||
|
|
@ -331,7 +331,7 @@ public class TestContextAotGenerator {
|
|||
* create {@link GenericApplicationContext GenericApplicationContexts}.
|
||||
* @throws TestContextAotException if an error occurs while loading the application
|
||||
* context or if one of the prerequisites is not met
|
||||
* @see AotContextLoader#loadContextForAotProcessing(MergedContextConfiguration)
|
||||
* @see AotContextLoader#loadContextForAotProcessing(MergedContextConfiguration, RuntimeHints)
|
||||
*/
|
||||
private GenericApplicationContext loadContextForAotProcessing(
|
||||
MergedContextConfiguration mergedConfig) throws TestContextAotException {
|
||||
|
|
@ -345,7 +345,7 @@ public class TestContextAotGenerator {
|
|||
|
||||
if (contextLoader instanceof AotContextLoader aotContextLoader) {
|
||||
try {
|
||||
ApplicationContext context = aotContextLoader.loadContextForAotProcessing(mergedConfig);
|
||||
ApplicationContext context = aotContextLoader.loadContextForAotProcessing(mergedConfig, this.runtimeHints);
|
||||
if (context instanceof GenericApplicationContext gac) {
|
||||
return gac;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
* Copyright 2002-2025 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.
|
||||
|
|
@ -19,6 +19,7 @@ package org.springframework.test.context.support;
|
|||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.aot.hint.RuntimeHints;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextInitializer;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
|
|
@ -225,8 +226,13 @@ public abstract class AbstractDelegatingSmartContextLoader implements AotContext
|
|||
* {@code ApplicationContext} from the supplied merged context configuration
|
||||
* @since 6.0
|
||||
* @see AotContextLoader#loadContextForAotProcessing(MergedContextConfiguration)
|
||||
* @deprecated as of Spring Framework 6.2.4, in favor of
|
||||
* {@link #loadContextForAotProcessing(MergedContextConfiguration, RuntimeHints)};
|
||||
* to be removed in Spring Framework 8.0
|
||||
*/
|
||||
@Deprecated(since = "6.2.4", forRemoval = true)
|
||||
@Override
|
||||
@SuppressWarnings("removal")
|
||||
public final ApplicationContext loadContextForAotProcessing(MergedContextConfiguration mergedConfig) throws Exception {
|
||||
AotContextLoader loader = getAotContextLoader(mergedConfig);
|
||||
if (logger.isTraceEnabled()) {
|
||||
|
|
@ -236,6 +242,33 @@ public abstract class AbstractDelegatingSmartContextLoader implements AotContext
|
|||
return loader.loadContextForAotProcessing(mergedConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delegates to an appropriate candidate {@code SmartContextLoader} to load
|
||||
* an {@link ApplicationContext} for AOT processing.
|
||||
* <p>Delegation is based on explicit knowledge of the implementations of the
|
||||
* default loaders. See {@link #loadContext(MergedContextConfiguration)} for
|
||||
* details.
|
||||
* @param mergedConfig the merged context configuration to use to load the application context
|
||||
* @param runtimeHints the runtime hints
|
||||
* @return a new application context
|
||||
* @throws IllegalArgumentException if the supplied merged configuration is {@code null}
|
||||
* @throws IllegalStateException if neither candidate loader is capable of loading an
|
||||
* {@code ApplicationContext} from the supplied merged context configuration
|
||||
* @since 6.2.4
|
||||
* @see AotContextLoader#loadContextForAotProcessing(MergedContextConfiguration, RuntimeHints)
|
||||
*/
|
||||
@Override
|
||||
public final ApplicationContext loadContextForAotProcessing(MergedContextConfiguration mergedConfig,
|
||||
RuntimeHints runtimeHints) throws Exception {
|
||||
|
||||
AotContextLoader loader = getAotContextLoader(mergedConfig);
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Delegating to %s to load context for AOT processing for %s"
|
||||
.formatted(name(loader), mergedConfig));
|
||||
}
|
||||
return loader.loadContextForAotProcessing(mergedConfig, runtimeHints);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delegates to an appropriate candidate {@code SmartContextLoader} to load
|
||||
* an {@link ApplicationContext} for AOT run-time execution.
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2022 the original author or authors.
|
||||
* Copyright 2002-2025 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.
|
||||
|
|
@ -21,6 +21,7 @@ import java.util.Arrays;
|
|||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.aot.hint.RuntimeHints;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionReader;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
|
|
@ -126,10 +127,41 @@ public abstract class AbstractGenericContextLoader extends AbstractContextLoader
|
|||
* @throws Exception if context loading failed
|
||||
* @since 6.0
|
||||
* @see AotContextLoader#loadContextForAotProcessing(MergedContextConfiguration)
|
||||
* @deprecated as of Spring Framework 6.2.4, in favor of
|
||||
* {@link #loadContextForAotProcessing(MergedContextConfiguration, RuntimeHints)};
|
||||
* to be removed in Spring Framework 8.0
|
||||
*/
|
||||
@Deprecated(since = "6.2.4", forRemoval = true)
|
||||
@Override
|
||||
@SuppressWarnings("removal")
|
||||
public final GenericApplicationContext loadContextForAotProcessing(MergedContextConfiguration mergedConfig)
|
||||
throws Exception {
|
||||
|
||||
return loadContext(mergedConfig, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a {@link GenericApplicationContext} for AOT build-time processing based
|
||||
* on the supplied {@link MergedContextConfiguration}.
|
||||
* <p>In contrast to {@link #loadContext(MergedContextConfiguration)}, this
|
||||
* method does not
|
||||
* {@linkplain org.springframework.context.ConfigurableApplicationContext#refresh()
|
||||
* refresh} the {@code ApplicationContext} or
|
||||
* {@linkplain org.springframework.context.ConfigurableApplicationContext#registerShutdownHook()
|
||||
* register a JVM shutdown hook} for it. Otherwise, this method implements
|
||||
* behavior identical to {@link #loadContext(MergedContextConfiguration)}.
|
||||
* @param mergedConfig the merged context configuration to use to load the
|
||||
* application context
|
||||
* @param runtimeHints the runtime hints
|
||||
* @return a new application context
|
||||
* @throws Exception if context loading failed
|
||||
* @since 6.2.4
|
||||
* @see AotContextLoader#loadContextForAotProcessing(MergedContextConfiguration, RuntimeHints)
|
||||
*/
|
||||
@Override
|
||||
public final GenericApplicationContext loadContextForAotProcessing(MergedContextConfiguration mergedConfig,
|
||||
RuntimeHints runtimeHints) throws Exception {
|
||||
|
||||
return loadContext(mergedConfig, true);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2023 the original author or authors.
|
||||
* Copyright 2002-2025 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.
|
||||
|
|
@ -20,6 +20,7 @@ import jakarta.servlet.ServletContext;
|
|||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.aot.hint.RuntimeHints;
|
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextInitializer;
|
||||
|
|
@ -120,10 +121,41 @@ public abstract class AbstractGenericWebContextLoader extends AbstractContextLoa
|
|||
* @throws Exception if context loading failed
|
||||
* @since 6.0
|
||||
* @see AotContextLoader#loadContextForAotProcessing(MergedContextConfiguration)
|
||||
* @deprecated as of Spring Framework 6.2.4, in favor of
|
||||
* {@link #loadContextForAotProcessing(MergedContextConfiguration, RuntimeHints)};
|
||||
* to be removed in Spring Framework 8.0
|
||||
*/
|
||||
@Deprecated(since = "6.2.4", forRemoval = true)
|
||||
@Override
|
||||
@SuppressWarnings("removal")
|
||||
public final GenericWebApplicationContext loadContextForAotProcessing(MergedContextConfiguration mergedConfig)
|
||||
throws Exception {
|
||||
|
||||
return loadContext(mergedConfig, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a {@link GenericWebApplicationContext} for AOT build-time processing based
|
||||
* on the supplied {@link MergedContextConfiguration}.
|
||||
* <p>In contrast to {@link #loadContext(MergedContextConfiguration)}, this
|
||||
* method does not
|
||||
* {@linkplain org.springframework.context.ConfigurableApplicationContext#refresh()
|
||||
* refresh} the {@code ApplicationContext} or
|
||||
* {@linkplain org.springframework.context.ConfigurableApplicationContext#registerShutdownHook()
|
||||
* register a JVM shutdown hook} for it. Otherwise, this method implements
|
||||
* behavior identical to {@link #loadContext(MergedContextConfiguration)}.
|
||||
* @param mergedConfig the merged context configuration to use to load the
|
||||
* application context
|
||||
* @param runtimeHints the runtime hints
|
||||
* @return a new web application context
|
||||
* @throws Exception if context loading failed
|
||||
* @since 6.2.4
|
||||
* @see AotContextLoader#loadContextForAotProcessing(MergedContextConfiguration, RuntimeHints)
|
||||
*/
|
||||
@Override
|
||||
public final GenericWebApplicationContext loadContextForAotProcessing(MergedContextConfiguration mergedConfig,
|
||||
RuntimeHints runtimeHints) throws Exception {
|
||||
|
||||
return loadContext(mergedConfig, true);
|
||||
}
|
||||
|
||||
|
|
@ -187,7 +219,7 @@ public abstract class AbstractGenericWebContextLoader extends AbstractContextLoa
|
|||
* register a JVM shutdown hook for it
|
||||
* @return a new web application context
|
||||
* @see org.springframework.test.context.SmartContextLoader#loadContext(MergedContextConfiguration)
|
||||
* @see org.springframework.test.context.aot.AotContextLoader#loadContextForAotProcessing(MergedContextConfiguration)
|
||||
* @see org.springframework.test.context.aot.AotContextLoader#loadContextForAotProcessing(MergedContextConfiguration, RuntimeHints)
|
||||
*/
|
||||
private GenericWebApplicationContext loadContext(
|
||||
MergedContextConfiguration mergedConfig, boolean forAotProcessing) throws Exception {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Copyright 2002-2025 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 org.springframework.context.ApplicationContextInitializer;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.support.GenericApplicationContext;
|
||||
import org.springframework.context.support.StaticApplicationContext;
|
||||
import org.springframework.test.context.MergedContextConfiguration;
|
||||
import org.springframework.test.context.support.AbstractContextLoader;
|
||||
|
||||
/**
|
||||
* @author Sam Brannen
|
||||
* @since 6.2.4
|
||||
*/
|
||||
class AbstractAotContextLoader extends AbstractContextLoader implements AotContextLoader {
|
||||
|
||||
@Override
|
||||
public final GenericApplicationContext loadContext(MergedContextConfiguration mergedConfig) {
|
||||
return new StaticApplicationContext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final GenericApplicationContext loadContextForAotRuntime(MergedContextConfiguration mergedConfig,
|
||||
ApplicationContextInitializer<ConfigurableApplicationContext> initializer) {
|
||||
|
||||
return loadContext(mergedConfig);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final String getResourceSuffix() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
* Copyright 2002-2025 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.lang.reflect.Method;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.aot.generate.InMemoryGeneratedFiles;
|
||||
import org.springframework.aot.hint.ExecutableMode;
|
||||
import org.springframework.aot.hint.RuntimeHints;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.support.GenericApplicationContext;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.ContextConfigurationAttributes;
|
||||
import org.springframework.test.context.MergedContextConfiguration;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.springframework.aot.hint.predicate.RuntimeHintsPredicates.reflection;
|
||||
|
||||
/**
|
||||
* Tests for registering run-time hints within an {@link AotContextLoader}, tested
|
||||
* via the {@link TestContextAotGenerator}.
|
||||
*
|
||||
* @author Sam Brannen
|
||||
* @since 6.2.4
|
||||
*/
|
||||
class AotContextLoaderRuntimeHintsTests {
|
||||
|
||||
@Test // gh-34513
|
||||
void aotContextLoaderCanRegisterRuntimeHints() {
|
||||
RuntimeHints runtimeHints = new RuntimeHints();
|
||||
TestContextAotGenerator generator = new TestContextAotGenerator(new InMemoryGeneratedFiles(), runtimeHints);
|
||||
|
||||
generator.processAheadOfTime(Stream.of(TestCase.class));
|
||||
|
||||
assertThat(reflection().onMethod(ConfigWithMain.class, "main").invoke()).accepts(runtimeHints);
|
||||
}
|
||||
|
||||
|
||||
@ContextConfiguration(classes = ConfigWithMain.class, loader = RuntimeHintsAwareAotContextLoader.class)
|
||||
static class TestCase {
|
||||
}
|
||||
|
||||
@Configuration(proxyBeanMethods = false)
|
||||
static class ConfigWithMain {
|
||||
|
||||
public static void main(String[] args) {
|
||||
// Mimics main() method for Spring Boot app
|
||||
}
|
||||
}
|
||||
|
||||
static class RuntimeHintsAwareAotContextLoader extends AbstractAotContextLoader {
|
||||
|
||||
@Override
|
||||
public void processContextConfiguration(ContextConfigurationAttributes configAttributes) {
|
||||
/* no-op */
|
||||
}
|
||||
|
||||
@Override
|
||||
public GenericApplicationContext loadContextForAotProcessing(MergedContextConfiguration mergedConfig,
|
||||
RuntimeHints runtimeHints) throws Exception {
|
||||
|
||||
// Mimics SpringBootContextLoader
|
||||
Method mainMethod = mergedConfig.getClasses()[0].getMethod("main", String[].class);
|
||||
runtimeHints.reflection().registerMethod(mainMethod, ExecutableMode.INVOKE);
|
||||
|
||||
return loadContext(mergedConfig);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,109 @@
|
|||
/*
|
||||
* Copyright 2002-2025 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.lang.reflect.Method;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.aot.hint.RuntimeHints;
|
||||
import org.springframework.context.support.GenericApplicationContext;
|
||||
import org.springframework.test.context.MergedContextConfiguration;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.mockito.BDDMockito.never;
|
||||
import static org.mockito.BDDMockito.spy;
|
||||
import static org.mockito.BDDMockito.then;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link AotContextLoader}.
|
||||
*
|
||||
* @author Sam Brannen
|
||||
* @since 6.2.4
|
||||
*/
|
||||
class AotContextLoaderTests {
|
||||
|
||||
/**
|
||||
* Verifies that a legacy {@link AotContextLoader} which only overrides
|
||||
* {@link AotContextLoader#loadContextForAotProcessing(MergedContextConfiguration)
|
||||
* is still supported.
|
||||
*/
|
||||
@Test // gh-34513
|
||||
@SuppressWarnings("removal")
|
||||
void legacyAotContextLoader() throws Exception {
|
||||
// Prerequisites
|
||||
assertDeclaringClasses(LegacyAotContextLoader.class, LegacyAotContextLoader.class, AotContextLoader.class);
|
||||
|
||||
AotContextLoader loader = spy(new LegacyAotContextLoader());
|
||||
MergedContextConfiguration mergedConfig = new MergedContextConfiguration(getClass(), null, null, null, loader);
|
||||
|
||||
loader.loadContextForAotProcessing(mergedConfig, new RuntimeHints());
|
||||
|
||||
then(loader).should().loadContextForAotProcessing(mergedConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
* Verifies that a modern {@link AotContextLoader} which only overrides
|
||||
* {@link AotContextLoader#loadContextForAotProcessing(MergedContextConfiguration, RuntimeHints)
|
||||
* is supported.
|
||||
*/
|
||||
@Test // gh-34513
|
||||
@SuppressWarnings("removal")
|
||||
void runtimeHintsAwareAotContextLoader() throws Exception {
|
||||
// Prerequisites
|
||||
assertDeclaringClasses(RuntimeHintsAwareAotContextLoader.class, AotContextLoader.class, RuntimeHintsAwareAotContextLoader.class);
|
||||
|
||||
AotContextLoader loader = spy(new RuntimeHintsAwareAotContextLoader());
|
||||
MergedContextConfiguration mergedConfig = new MergedContextConfiguration(getClass(), null, null, null, loader);
|
||||
|
||||
loader.loadContextForAotProcessing(mergedConfig, new RuntimeHints());
|
||||
|
||||
then(loader).should(never()).loadContextForAotProcessing(mergedConfig);
|
||||
}
|
||||
|
||||
|
||||
private static void assertDeclaringClasses(Class<? extends AotContextLoader> loaderClass,
|
||||
Class<?> declaringClassForLegacyMethod, Class<?> declaringClassForNewMethod) throws Exception {
|
||||
|
||||
Method legacyMethod = loaderClass.getMethod("loadContextForAotProcessing", MergedContextConfiguration.class);
|
||||
Method newMethod = loaderClass.getMethod("loadContextForAotProcessing", MergedContextConfiguration.class, RuntimeHints.class);
|
||||
|
||||
assertThat(legacyMethod.getDeclaringClass()).isEqualTo(declaringClassForLegacyMethod);
|
||||
assertThat(newMethod.getDeclaringClass()).isEqualTo(declaringClassForNewMethod);
|
||||
}
|
||||
|
||||
|
||||
private static class LegacyAotContextLoader extends AbstractAotContextLoader {
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("removal")
|
||||
public GenericApplicationContext loadContextForAotProcessing(MergedContextConfiguration mergedConfig) {
|
||||
return loadContext(mergedConfig);
|
||||
}
|
||||
}
|
||||
|
||||
private static class RuntimeHintsAwareAotContextLoader extends AbstractAotContextLoader {
|
||||
|
||||
@Override
|
||||
public GenericApplicationContext loadContextForAotProcessing(MergedContextConfiguration mergedConfig,
|
||||
RuntimeHints runtimeHints) {
|
||||
|
||||
return loadContext(mergedConfig);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 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.
|
||||
|
|
@ -20,6 +20,7 @@ import java.util.Arrays;
|
|||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.aot.hint.RuntimeHints;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.test.context.MergedContextConfiguration;
|
||||
|
|
@ -79,7 +80,7 @@ class AnnotationConfigContextLoaderTests {
|
|||
AnnotatedFooConfigInnerClassTestCase.class, EMPTY_STRING_ARRAY,
|
||||
new Class<?>[] {AnnotatedFooConfigInnerClassTestCase.FooConfig.class},
|
||||
EMPTY_STRING_ARRAY, contextLoader);
|
||||
ConfigurableApplicationContext context = contextLoader.loadContextForAotProcessing(mergedConfig);
|
||||
ConfigurableApplicationContext context = contextLoader.loadContextForAotProcessing(mergedConfig, new RuntimeHints());
|
||||
assertThat(context.isActive()).as("ApplicationContext is active").isFalse();
|
||||
assertThat(Arrays.stream(context.getBeanDefinitionNames())).anyMatch(name -> name.contains("FooConfig"));
|
||||
context.close();
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2024 the original author or authors.
|
||||
* Copyright 2002-2025 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.
|
||||
|
|
@ -21,6 +21,7 @@ import java.util.Arrays;
|
|||
import org.junit.jupiter.api.Nested;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.aot.hint.RuntimeHints;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
|
|
@ -181,7 +182,7 @@ class DelegatingSmartContextLoaderTests {
|
|||
private void assertApplicationContextLoadsForAotProcessing(MergedContextConfiguration mergedConfig,
|
||||
String expectedBeanDefName) throws Exception {
|
||||
|
||||
ApplicationContext context = loader.loadContextForAotProcessing(mergedConfig);
|
||||
ApplicationContext context = loader.loadContextForAotProcessing(mergedConfig, new RuntimeHints());
|
||||
assertThat(context).isInstanceOf(ConfigurableApplicationContext.class);
|
||||
ConfigurableApplicationContext cac = (ConfigurableApplicationContext) context;
|
||||
assertThat(cac.isActive()).as("ApplicationContext is active").isFalse();
|
||||
|
|
|
|||
Loading…
Reference in New Issue