Polish Javadoc and internals of the TestContext framework
This commit is contained in:
parent
c32ff17821
commit
e53c7ae6f5
|
@ -28,6 +28,10 @@ import org.springframework.test.context.SmartContextLoader;
|
|||
* {@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)
|
||||
* support.
|
||||
*
|
||||
* <p>As of Spring Framework 6.0, AOT infrastructure requires that an {@code AotContextLoader}
|
||||
* create a {@link org.springframework.context.support.GenericApplicationContext
|
||||
* GenericApplicationContext} for both build-time processing and run-time execution.
|
||||
|
@ -47,7 +51,7 @@ public interface AotContextLoader extends SmartContextLoader {
|
|||
* refresh} the {@code ApplicationContext} or
|
||||
* {@linkplain org.springframework.context.ConfigurableApplicationContext#registerShutdownHook()
|
||||
* register a JVM shutdown hook} for it. Otherwise, this method should implement
|
||||
* behavior identical to {@link #loadContext(MergedContextConfiguration)}.
|
||||
* behavior identical to {@code loadContext(MergedContextConfiguration)}.
|
||||
* @param mergedConfig the merged context configuration to use to load the
|
||||
* application context
|
||||
* @return a new {@code GenericApplicationContext}
|
||||
|
|
|
@ -122,7 +122,7 @@ public class TestContextAotGenerator {
|
|||
generationContext.writeGeneratedContent();
|
||||
}
|
||||
catch (Exception ex) {
|
||||
logger.warn(LogMessage.format("Failed to generate AOT artifacts for test classes [%s]",
|
||||
logger.warn(LogMessage.format("Failed to generate AOT artifacts for test classes %s",
|
||||
testClasses.stream().map(Class::getName).toList()), ex);
|
||||
}
|
||||
});
|
||||
|
|
|
@ -105,18 +105,19 @@ public class DefaultCacheAwareContextLoaderDelegate implements CacheAwareContext
|
|||
context = loadContextInternal(mergedContextConfiguration);
|
||||
}
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(String.format("Storing ApplicationContext [%s] in cache under key [%s]",
|
||||
logger.debug("Storing ApplicationContext [%s] in cache under key %s".formatted(
|
||||
System.identityHashCode(context), mergedContextConfiguration));
|
||||
}
|
||||
this.contextCache.put(mergedContextConfiguration, context);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
throw new IllegalStateException("Failed to load ApplicationContext", ex);
|
||||
throw new IllegalStateException(
|
||||
"Failed to load ApplicationContext for " + mergedContextConfiguration, ex);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(String.format("Retrieved ApplicationContext [%s] from cache with key [%s]",
|
||||
logger.debug("Retrieved ApplicationContext [%s] from cache with key %s".formatted(
|
||||
System.identityHashCode(context), mergedContextConfiguration));
|
||||
}
|
||||
}
|
||||
|
@ -150,17 +151,16 @@ public class DefaultCacheAwareContextLoaderDelegate implements CacheAwareContext
|
|||
protected ApplicationContext loadContextInternal(MergedContextConfiguration mergedContextConfiguration)
|
||||
throws Exception {
|
||||
|
||||
ContextLoader contextLoader = mergedContextConfiguration.getContextLoader();
|
||||
Assert.notNull(contextLoader, "Cannot load an ApplicationContext with a NULL 'contextLoader'. " +
|
||||
"Consider annotating your test class with @ContextConfiguration or @ContextHierarchy.");
|
||||
|
||||
ContextLoader contextLoader = getContextLoader(mergedContextConfiguration);
|
||||
if (contextLoader instanceof SmartContextLoader smartContextLoader) {
|
||||
return smartContextLoader.loadContext(mergedContextConfiguration);
|
||||
}
|
||||
else {
|
||||
String[] locations = mergedContextConfiguration.getLocations();
|
||||
Assert.notNull(locations, "Cannot load an ApplicationContext with a NULL 'locations' array. " +
|
||||
"Consider annotating your test class with @ContextConfiguration or @ContextHierarchy.");
|
||||
Assert.notNull(locations, """
|
||||
Cannot load an ApplicationContext with a NULL 'locations' array. \
|
||||
Consider annotating test class [%s] with @ContextConfiguration or \
|
||||
@ContextHierarchy.""".formatted(mergedContextConfiguration.getTestClass().getName()));
|
||||
return contextLoader.loadContext(locations);
|
||||
}
|
||||
}
|
||||
|
@ -172,8 +172,8 @@ public class DefaultCacheAwareContextLoaderDelegate implements CacheAwareContext
|
|||
Assert.state(contextInitializer != null,
|
||||
() -> "Failed to load AOT ApplicationContextInitializer for test class [%s]"
|
||||
.formatted(testClass.getName()));
|
||||
ContextLoader contextLoader = getContextLoader(mergedConfig);
|
||||
logger.info(LogMessage.format("Loading ApplicationContext in AOT mode for %s", mergedConfig));
|
||||
ContextLoader contextLoader = mergedConfig.getContextLoader();
|
||||
if (!((contextLoader instanceof AotContextLoader aotContextLoader) &&
|
||||
(aotContextLoader.loadContextForAotRuntime(mergedConfig, contextInitializer)
|
||||
instanceof GenericApplicationContext gac))) {
|
||||
|
@ -187,6 +187,15 @@ public class DefaultCacheAwareContextLoaderDelegate implements CacheAwareContext
|
|||
return gac;
|
||||
}
|
||||
|
||||
private ContextLoader getContextLoader(MergedContextConfiguration mergedConfig) {
|
||||
ContextLoader contextLoader = mergedConfig.getContextLoader();
|
||||
Assert.notNull(contextLoader, """
|
||||
Cannot load an ApplicationContext with a NULL 'contextLoader'. \
|
||||
Consider annotating test class [%s] with @ContextConfiguration or \
|
||||
@ContextHierarchy.""".formatted(mergedConfig.getTestClass().getName()));
|
||||
return contextLoader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if we are running in AOT mode for the supplied test class.
|
||||
*/
|
||||
|
|
|
@ -60,12 +60,17 @@ import org.springframework.util.Assert;
|
|||
* (e.g., XML configuration files and Groovy scripts) or annotated classes,
|
||||
* but not both simultaneously.
|
||||
*
|
||||
* <p>As of Spring 3.2, a test class may optionally declare neither path-based
|
||||
* <p>As of Spring Framework 3.2, a test class may optionally declare neither path-based
|
||||
* resource locations nor annotated classes and instead declare only {@linkplain
|
||||
* ContextConfiguration#initializers application context initializers}. In such
|
||||
* cases, an attempt will still be made to detect defaults, but their absence will
|
||||
* not result in an exception.
|
||||
*
|
||||
* <p>As of Spring Framework 6.0, this class implements {@link AotContextLoader}.
|
||||
* Consequently, the candidate {@link #getXmlLoader()} and
|
||||
* {@link #getAnnotationConfigLoader()} must also implement {@code AotContextLoader}
|
||||
* in order to provide AOT support.
|
||||
*
|
||||
* @author Sam Brannen
|
||||
* @author Phillip Webb
|
||||
* @since 3.2
|
||||
|
@ -195,144 +200,103 @@ public abstract class AbstractDelegatingSmartContextLoader implements AotContext
|
|||
* </ul>
|
||||
* @param mergedConfig the merged context configuration to use to load the application context
|
||||
* @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
|
||||
*/
|
||||
@Override
|
||||
public final ApplicationContext loadContext(MergedContextConfiguration mergedConfig) throws Exception {
|
||||
return loadContext(mergedConfig, true);
|
||||
SmartContextLoader loader = getContextLoader(mergedConfig);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Delegating to %s to load context for %s".formatted(name(loader), mergedConfig));
|
||||
}
|
||||
return loader.loadContext(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 for {@linkplain #getXmlLoader() XML configuration files and
|
||||
* Groovy scripts} and {@linkplain #getAnnotationConfigLoader() annotated classes}.
|
||||
* Specifically, the delegation algorithm is as follows:
|
||||
* <ul>
|
||||
* <li>If the resource locations in the supplied {@code MergedContextConfiguration}
|
||||
* are not empty and the annotated classes are empty,
|
||||
* the XML-based loader will load the {@code ApplicationContext}.</li>
|
||||
* <li>If the annotated classes in the supplied {@code MergedContextConfiguration}
|
||||
* are not empty and the resource locations are empty,
|
||||
* the annotation-based loader will load the {@code ApplicationContext}.</li>
|
||||
* </ul>
|
||||
* default loaders. See {@link #loadContext(MergedContextConfiguration)} for
|
||||
* details.
|
||||
* @param mergedConfig the merged context configuration to use to load the application context
|
||||
* @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.0
|
||||
* @see AotContextLoader#loadContextForAotProcessing(MergedContextConfiguration)
|
||||
*/
|
||||
@Override
|
||||
public final ApplicationContext loadContextForAotProcessing(MergedContextConfiguration mergedConfig) throws Exception {
|
||||
return loadContext(mergedConfig, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final ApplicationContext loadContextForAotRuntime(MergedContextConfiguration mergedConfig,
|
||||
ApplicationContextInitializer<ConfigurableApplicationContext> initializer) throws Exception {
|
||||
return getAotContextLoader(mergedConfig, "load").loadContextForAotRuntime(mergedConfig, initializer);
|
||||
AotContextLoader loader = getAotContextLoader(mergedConfig);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Delegating to %s to load context for AOT processing for %s"
|
||||
.formatted(name(loader), mergedConfig));
|
||||
}
|
||||
return loader.loadContextForAotProcessing(mergedConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delegates to an appropriate candidate {@code SmartContextLoader} to load
|
||||
* an {@link ApplicationContext}.
|
||||
* an {@link ApplicationContext} for AOT run-time execution.
|
||||
* <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 refresh whether to refresh the {@code ApplicationContext} and register
|
||||
* a JVM shutdown hook for it
|
||||
* @param initializer the {@code ApplicationContextInitializer} that should
|
||||
* be applied to the context in order to recreate bean definitions
|
||||
* @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.0
|
||||
* @see AotContextLoader#loadContextForAotRuntime(MergedContextConfiguration, ApplicationContextInitializer)
|
||||
*/
|
||||
private ApplicationContext loadContext(MergedContextConfiguration mergedConfig, boolean refresh) throws Exception {
|
||||
assertPreconditions(mergedConfig, "load");
|
||||
@Override
|
||||
public final ApplicationContext loadContextForAotRuntime(MergedContextConfiguration mergedConfig,
|
||||
ApplicationContextInitializer<ConfigurableApplicationContext> initializer) throws Exception {
|
||||
|
||||
AotContextLoader loader = getAotContextLoader(mergedConfig);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Delegating to %s to load context for AOT execution for %s"
|
||||
.formatted(name(loader), mergedConfig));
|
||||
}
|
||||
return loader.loadContextForAotRuntime(mergedConfig, initializer);
|
||||
}
|
||||
|
||||
private SmartContextLoader getContextLoader(MergedContextConfiguration mergedConfig) {
|
||||
Assert.notNull(mergedConfig, "MergedContextConfiguration must not be null");
|
||||
Assert.state(!(mergedConfig.hasLocations() && mergedConfig.hasClasses()), () -> """
|
||||
Neither %s nor %s is able to load an ApplicationContext for %s: \
|
||||
declare either 'locations' or 'classes' but not both.""".formatted(
|
||||
name(getXmlLoader()), name(getAnnotationConfigLoader()), mergedConfig));
|
||||
|
||||
SmartContextLoader[] candidates = {getXmlLoader(), getAnnotationConfigLoader()};
|
||||
for (SmartContextLoader loader : candidates) {
|
||||
// Determine if each loader can load a context from the mergedConfig. If it
|
||||
// can, let it; otherwise, keep iterating.
|
||||
if (supports(loader, mergedConfig)) {
|
||||
return delegateLoading(loader, mergedConfig, refresh);
|
||||
return loader;
|
||||
}
|
||||
}
|
||||
|
||||
// If neither of the candidates supports the mergedConfig based on resources but
|
||||
// ACIs or customizers were declared, then delegate to the annotation config
|
||||
// loader.
|
||||
if (!mergedConfig.getContextInitializerClasses().isEmpty() || !mergedConfig.getContextCustomizers().isEmpty()) {
|
||||
return delegateLoading(getAnnotationConfigLoader(), mergedConfig, refresh);
|
||||
// ACIs or customizers were declared, then delegate to the annotation config loader.
|
||||
if (hasInitializersOrCustomizers(mergedConfig)) {
|
||||
return getAnnotationConfigLoader();
|
||||
}
|
||||
|
||||
// else...
|
||||
throw new IllegalStateException(String.format(
|
||||
"Neither %s nor %s is able to load an ApplicationContext for %s.",
|
||||
name(getXmlLoader()), name(getAnnotationConfigLoader()), mergedConfig));
|
||||
}
|
||||
|
||||
private static void delegateProcessing(SmartContextLoader loader, ContextConfigurationAttributes configAttributes) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(String.format("Delegating to %s to process context configuration %s.",
|
||||
name(loader), configAttributes));
|
||||
}
|
||||
loader.processContextConfiguration(configAttributes);
|
||||
}
|
||||
|
||||
private static ApplicationContext delegateLoading(
|
||||
SmartContextLoader loader, MergedContextConfiguration mergedConfig, boolean refresh)
|
||||
throws Exception {
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(String.format("Delegating to %s to load context for %s.", name(loader), mergedConfig));
|
||||
}
|
||||
if (refresh) {
|
||||
return loader.loadContext(mergedConfig);
|
||||
}
|
||||
else {
|
||||
if (loader instanceof AotContextLoader aotContextLoader) {
|
||||
return aotContextLoader.loadContextForAotProcessing(mergedConfig);
|
||||
}
|
||||
throw new IllegalStateException(
|
||||
"%s must implement AotContextLoader to load the ApplicationContext for %s."
|
||||
.formatted(name(loader), mergedConfig));
|
||||
}
|
||||
}
|
||||
|
||||
private AotContextLoader getAotContextLoader(MergedContextConfiguration mergedConfig, String action) {
|
||||
assertPreconditions(mergedConfig, action);
|
||||
|
||||
SmartContextLoader[] candidates = {getXmlLoader(), getAnnotationConfigLoader()};
|
||||
for (SmartContextLoader loader : candidates) {
|
||||
// Determine if each loader can load a context from the mergedConfig. If it
|
||||
// can, let it; otherwise, keep iterating.
|
||||
if (loader instanceof AotContextLoader aotContextLoader && supports(loader, mergedConfig)) {
|
||||
return aotContextLoader;
|
||||
}
|
||||
}
|
||||
|
||||
// If neither of the candidates supports the mergedConfig based on resources but
|
||||
// ACIs or customizers were declared, then delegate to the annotation config
|
||||
// loader.
|
||||
if (getAnnotationConfigLoader() instanceof AotContextLoader aotContextLoader &&
|
||||
(!mergedConfig.getContextInitializerClasses().isEmpty() ||
|
||||
!mergedConfig.getContextCustomizers().isEmpty())) {
|
||||
return aotContextLoader;
|
||||
}
|
||||
|
||||
throw new IllegalStateException(
|
||||
"Neither %s nor %s is able to %s the ApplicationContext for %s.".formatted(
|
||||
name(getXmlLoader()), name(getAnnotationConfigLoader()), action, mergedConfig));
|
||||
"Neither %s nor %s is able to load an ApplicationContext for %s.".formatted(
|
||||
name(getXmlLoader()), name(getAnnotationConfigLoader()), mergedConfig));
|
||||
}
|
||||
|
||||
private void assertPreconditions(MergedContextConfiguration mergedConfig, String action) {
|
||||
Assert.notNull(mergedConfig, "MergedContextConfiguration must not be null");
|
||||
Assert.state(!(mergedConfig.hasLocations() && mergedConfig.hasClasses()), () -> """
|
||||
Neither %s nor %s is able to %s an ApplicationContext for %s: \
|
||||
declare either 'locations' or 'classes' but not both.""".formatted(
|
||||
name(getXmlLoader()), name(getAnnotationConfigLoader()), action, mergedConfig));
|
||||
private AotContextLoader getAotContextLoader(MergedContextConfiguration mergedConfig) {
|
||||
SmartContextLoader loader = getContextLoader(mergedConfig);
|
||||
if (!(loader instanceof AotContextLoader aotContextLoader)) {
|
||||
throw new IllegalStateException("%s must be an AotContextLoader".formatted(name(loader)));
|
||||
}
|
||||
return aotContextLoader;
|
||||
}
|
||||
|
||||
private boolean supports(SmartContextLoader loader, MergedContextConfiguration mergedConfig) {
|
||||
|
@ -344,6 +308,19 @@ public abstract class AbstractDelegatingSmartContextLoader implements AotContext
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
private static void delegateProcessing(SmartContextLoader loader, ContextConfigurationAttributes configAttributes) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Delegating to %s to process context configuration %s.".formatted(name(loader), configAttributes));
|
||||
}
|
||||
loader.processContextConfiguration(configAttributes);
|
||||
}
|
||||
|
||||
private static boolean hasInitializersOrCustomizers(MergedContextConfiguration mergedConfig) {
|
||||
return !(mergedConfig.getContextInitializerClasses().isEmpty() &&
|
||||
mergedConfig.getContextCustomizers().isEmpty());
|
||||
}
|
||||
|
||||
private static String name(SmartContextLoader loader) {
|
||||
return loader.getClass().getSimpleName();
|
||||
}
|
||||
|
|
|
@ -16,6 +16,8 @@
|
|||
|
||||
package org.springframework.test.context.support;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
|
@ -28,7 +30,7 @@ import org.springframework.context.annotation.AnnotationConfigUtils;
|
|||
import org.springframework.context.support.GenericApplicationContext;
|
||||
import org.springframework.test.context.MergedContextConfiguration;
|
||||
import org.springframework.test.context.aot.AotContextLoader;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Abstract, generic extension of {@link AbstractContextLoader} that loads a
|
||||
|
@ -104,12 +106,12 @@ public abstract class AbstractGenericContextLoader extends AbstractContextLoader
|
|||
*/
|
||||
@Override
|
||||
public final ApplicationContext loadContext(MergedContextConfiguration mergedConfig) throws Exception {
|
||||
return loadContext(mergedConfig, true);
|
||||
return loadContext(mergedConfig, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a {@link GenericApplicationContext} for the supplied
|
||||
* {@link MergedContextConfiguration}.
|
||||
* 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()
|
||||
|
@ -120,23 +122,38 @@ public abstract class AbstractGenericContextLoader extends AbstractContextLoader
|
|||
* @param mergedConfig the merged context configuration to use to load the
|
||||
* application context
|
||||
* @return a new application context
|
||||
* @throws Exception if context loading failed
|
||||
* @since 6.0
|
||||
* @see org.springframework.test.context.SmartContextLoader#loadContextForAotProcessing(MergedContextConfiguration)
|
||||
* @see AotContextLoader#loadContextForAotProcessing(MergedContextConfiguration)
|
||||
*/
|
||||
@Override
|
||||
public final ApplicationContext loadContextForAotProcessing(
|
||||
MergedContextConfiguration mergedConfig) throws Exception {
|
||||
|
||||
return loadContext(mergedConfig, false);
|
||||
public final GenericApplicationContext loadContextForAotProcessing(MergedContextConfiguration mergedConfig)
|
||||
throws Exception {
|
||||
return loadContext(mergedConfig, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a {@link GenericApplicationContext} for AOT run-time execution based on
|
||||
* the supplied {@link MergedContextConfiguration} and
|
||||
* {@link ApplicationContextInitializer}.
|
||||
* @param mergedConfig the merged context configuration to use to load the
|
||||
* application context
|
||||
* @param initializer the {@code ApplicationContextInitializer} that should
|
||||
* be applied to the context in order to recreate bean definitions
|
||||
* @return a new application context
|
||||
* @throws Exception if context loading failed
|
||||
* @since 6.0
|
||||
* @see AotContextLoader#loadContextForAotRuntime(MergedContextConfiguration, ApplicationContextInitializer)
|
||||
*/
|
||||
@Override
|
||||
public final ApplicationContext loadContextForAotRuntime(MergedContextConfiguration mergedConfig,
|
||||
public final GenericApplicationContext loadContextForAotRuntime(MergedContextConfiguration mergedConfig,
|
||||
ApplicationContextInitializer<ConfigurableApplicationContext> initializer) throws Exception {
|
||||
|
||||
Assert.notNull(mergedConfig, "MergedContextConfiguration must not be null");
|
||||
Assert.notNull(initializer, "ApplicationContextInitializer must not be null");
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(String.format("Loading ApplicationContext for AOT runtime for merged context configuration [%s].",
|
||||
mergedConfig));
|
||||
logger.debug("Loading ApplicationContext for AOT runtime for merged context configuration " + mergedConfig);
|
||||
}
|
||||
|
||||
validateMergedContextConfiguration(mergedConfig);
|
||||
|
@ -156,16 +173,17 @@ public abstract class AbstractGenericContextLoader extends AbstractContextLoader
|
|||
* {@link MergedContextConfiguration}.
|
||||
* @param mergedConfig the merged context configuration to use to load the
|
||||
* application context
|
||||
* @param refresh whether to refresh the {@code ApplicationContext} and register
|
||||
* a JVM shutdown hook for it
|
||||
* @param forAotProcessing {@code true} if the context is being loaded for
|
||||
* AOT processing, meaning not to refresh the {@code ApplicationContext} or
|
||||
* register a JVM shutdown hook for it
|
||||
* @return a new application context
|
||||
*/
|
||||
private final GenericApplicationContext loadContext(
|
||||
MergedContextConfiguration mergedConfig, boolean refresh) throws Exception {
|
||||
MergedContextConfiguration mergedConfig, boolean forAotProcessing) throws Exception {
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(String.format("Loading ApplicationContext for merged context configuration [%s].",
|
||||
mergedConfig));
|
||||
logger.debug("Loading ApplicationContext %sfor merged context configuration %s"
|
||||
.formatted((forAotProcessing ? "for AOT processing " : ""), mergedConfig));
|
||||
}
|
||||
|
||||
validateMergedContextConfiguration(mergedConfig);
|
||||
|
@ -184,7 +202,7 @@ public abstract class AbstractGenericContextLoader extends AbstractContextLoader
|
|||
customizeContext(context);
|
||||
customizeContext(context, mergedConfig);
|
||||
|
||||
if (refresh) {
|
||||
if (!forAotProcessing) {
|
||||
context.refresh();
|
||||
context.registerShutdownHook();
|
||||
}
|
||||
|
@ -236,14 +254,13 @@ public abstract class AbstractGenericContextLoader extends AbstractContextLoader
|
|||
* @see org.springframework.test.context.ContextLoader#loadContext
|
||||
* @see GenericApplicationContext
|
||||
* @see #loadContext(MergedContextConfiguration)
|
||||
* @deprecated as of Spring Framework 6.0, in favor of {@link #loadContextForAotProcessing(MergedContextConfiguration)}
|
||||
* @deprecated as of Spring Framework 6.0, in favor of {@link #loadContext(MergedContextConfiguration)}
|
||||
*/
|
||||
@Deprecated
|
||||
@Override
|
||||
public final ConfigurableApplicationContext loadContext(String... locations) throws Exception {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(String.format("Loading ApplicationContext for locations [%s].",
|
||||
StringUtils.arrayToCommaDelimitedString(locations)));
|
||||
logger.debug("Loading ApplicationContext for locations " + Arrays.toString(locations));
|
||||
}
|
||||
|
||||
GenericApplicationContext context = createContext();
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2019 the original author or authors.
|
||||
* 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.
|
||||
|
@ -16,6 +16,8 @@
|
|||
|
||||
package org.springframework.test.context.support;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
|
@ -24,7 +26,6 @@ import org.springframework.context.annotation.AnnotatedBeanDefinitionReader;
|
|||
import org.springframework.context.support.GenericApplicationContext;
|
||||
import org.springframework.test.context.ContextConfigurationAttributes;
|
||||
import org.springframework.test.context.MergedContextConfiguration;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* Concrete implementation of {@link AbstractGenericContextLoader} that loads
|
||||
|
@ -155,10 +156,11 @@ public class AnnotationConfigContextLoader extends AbstractGenericContextLoader
|
|||
@Override
|
||||
protected void validateMergedContextConfiguration(MergedContextConfiguration mergedConfig) {
|
||||
if (mergedConfig.hasLocations()) {
|
||||
String msg = String.format("Test class [%s] has been configured with @ContextConfiguration's 'locations' " +
|
||||
"(or 'value') attribute %s, but %s does not support resource locations.",
|
||||
mergedConfig.getTestClass().getName(), ObjectUtils.nullSafeToString(mergedConfig.getLocations()),
|
||||
getClass().getSimpleName());
|
||||
String msg = """
|
||||
Test class [%s] has been configured with @ContextConfiguration's 'locations' \
|
||||
(or 'value') attribute %s, but %s does not support resource locations."""
|
||||
.formatted(mergedConfig.getTestClass().getName(),
|
||||
Arrays.toString(mergedConfig.getLocations()), getClass().getSimpleName());
|
||||
logger.error(msg);
|
||||
throw new IllegalStateException(msg);
|
||||
}
|
||||
|
@ -181,7 +183,7 @@ public class AnnotationConfigContextLoader extends AbstractGenericContextLoader
|
|||
protected void loadBeanDefinitions(GenericApplicationContext context, MergedContextConfiguration mergedConfig) {
|
||||
Class<?>[] componentClasses = mergedConfig.getClasses();
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Registering component classes: " + ObjectUtils.nullSafeToString(componentClasses));
|
||||
logger.debug("Registering component classes: " + Arrays.toString(componentClasses));
|
||||
}
|
||||
new AnnotatedBeanDefinitionReader(context).register(componentClasses);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2021 the original author or authors.
|
||||
* 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.
|
||||
|
@ -123,13 +123,14 @@ public class DefaultTestContext implements TestContext {
|
|||
public ApplicationContext getApplicationContext() {
|
||||
ApplicationContext context = this.cacheAwareContextLoaderDelegate.loadContext(this.mergedContextConfiguration);
|
||||
if (context instanceof ConfigurableApplicationContext cac) {
|
||||
Assert.state(cac.isActive(), () ->
|
||||
"The ApplicationContext loaded for [" + this.mergedContextConfiguration +
|
||||
"] is not active. This may be due to one of the following reasons: " +
|
||||
"1) the context was closed programmatically by user code; " +
|
||||
"2) the context was closed during parallel test execution either " +
|
||||
"according to @DirtiesContext semantics or due to automatic eviction " +
|
||||
"from the ContextCache due to a maximum cache size policy.");
|
||||
Assert.state(cac.isActive(), () -> """
|
||||
The ApplicationContext loaded for %s is not active. \
|
||||
This may be due to one of the following reasons: \
|
||||
1) the context was closed programmatically by user code; \
|
||||
2) the context was closed during parallel test execution either \
|
||||
according to @DirtiesContext semantics or due to automatic eviction \
|
||||
from the ContextCache due to a maximum cache size policy."""
|
||||
.formatted(this.mergedContextConfiguration));
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
@ -206,7 +207,7 @@ public class DefaultTestContext implements TestContext {
|
|||
Assert.notNull(computeFunction, "Compute function must not be null");
|
||||
Object value = this.attributes.computeIfAbsent(name, computeFunction);
|
||||
Assert.state(value != null,
|
||||
() -> String.format("Compute function must not return null for attribute named '%s'", name));
|
||||
() -> "Compute function must not return null for attribute named '%s'".formatted(name));
|
||||
return (T) value;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2014 the original author or authors.
|
||||
* 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.
|
||||
|
@ -16,11 +16,12 @@
|
|||
|
||||
package org.springframework.test.context.support;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.springframework.beans.factory.support.BeanDefinitionReader;
|
||||
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
|
||||
import org.springframework.context.support.GenericApplicationContext;
|
||||
import org.springframework.test.context.MergedContextConfiguration;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* Concrete implementation of {@link AbstractGenericContextLoader} that reads
|
||||
|
@ -64,10 +65,10 @@ public class GenericXmlContextLoader extends AbstractGenericContextLoader {
|
|||
@Override
|
||||
protected void validateMergedContextConfiguration(MergedContextConfiguration mergedConfig) {
|
||||
if (mergedConfig.hasClasses()) {
|
||||
String msg = String.format(
|
||||
"Test class [%s] has been configured with @ContextConfiguration's 'classes' attribute %s, "
|
||||
+ "but %s does not support annotated classes.", mergedConfig.getTestClass().getName(),
|
||||
ObjectUtils.nullSafeToString(mergedConfig.getClasses()), getClass().getSimpleName());
|
||||
String msg = """
|
||||
Test class [%s] has been configured with @ContextConfiguration's 'classes' attribute %s, \
|
||||
but %s does not support annotated classes.""".formatted(mergedConfig.getTestClass().getName(),
|
||||
Arrays.toString(mergedConfig.getClasses()), getClass().getSimpleName());
|
||||
logger.error(msg);
|
||||
throw new IllegalStateException(msg);
|
||||
}
|
||||
|
|
|
@ -64,57 +64,6 @@ public abstract class AbstractGenericWebContextLoader extends AbstractContextLoa
|
|||
protected static final Log logger = LogFactory.getLog(AbstractGenericWebContextLoader.class);
|
||||
|
||||
|
||||
// AotContextLoader
|
||||
|
||||
/**
|
||||
* Load a {@link GenericWebApplicationContext} for 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
|
||||
* @return a new web application context
|
||||
* @since 6.0
|
||||
* @see org.springframework.test.context.aot.AotContextLoader#loadContextForAotProcessing(MergedContextConfiguration)
|
||||
* @see GenericWebApplicationContext
|
||||
*/
|
||||
@Override
|
||||
public final ApplicationContext loadContextForAotProcessing(
|
||||
MergedContextConfiguration mergedConfig) throws Exception {
|
||||
|
||||
return loadContext(mergedConfig, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final ApplicationContext loadContextForAotRuntime(MergedContextConfiguration mergedConfig,
|
||||
ApplicationContextInitializer<ConfigurableApplicationContext> initializer) throws Exception {
|
||||
|
||||
if (!(mergedConfig instanceof WebMergedContextConfiguration webMergedConfig)) {
|
||||
throw new IllegalArgumentException("""
|
||||
Cannot load WebApplicationContext from non-web merged context configuration %s. \
|
||||
Consider annotating your test class with @WebAppConfiguration."""
|
||||
.formatted(mergedConfig));
|
||||
}
|
||||
|
||||
validateMergedContextConfiguration(webMergedConfig);
|
||||
|
||||
GenericWebApplicationContext context = createContext();
|
||||
configureWebResources(context, webMergedConfig);
|
||||
prepareContext(context, webMergedConfig);
|
||||
initializer.initialize(context);
|
||||
customizeContext(context, webMergedConfig);
|
||||
context.refresh();
|
||||
return context;
|
||||
}
|
||||
|
||||
|
||||
// SmartContextLoader
|
||||
|
||||
/**
|
||||
* Load a {@link GenericWebApplicationContext} for the supplied
|
||||
* {@link MergedContextConfiguration}.
|
||||
|
@ -149,26 +98,86 @@ public abstract class AbstractGenericWebContextLoader extends AbstractContextLoa
|
|||
* application context
|
||||
* @return a new web application context
|
||||
* @see org.springframework.test.context.SmartContextLoader#loadContext(MergedContextConfiguration)
|
||||
* @see GenericWebApplicationContext
|
||||
*/
|
||||
@Override
|
||||
public final ApplicationContext loadContext(MergedContextConfiguration mergedConfig) throws Exception {
|
||||
return loadContext(mergedConfig, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @return a new web application context
|
||||
* @throws Exception if context loading failed
|
||||
* @since 6.0
|
||||
* @see AotContextLoader#loadContextForAotProcessing(MergedContextConfiguration)
|
||||
*/
|
||||
@Override
|
||||
public final GenericWebApplicationContext loadContextForAotProcessing(MergedContextConfiguration mergedConfig)
|
||||
throws Exception {
|
||||
return loadContext(mergedConfig, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a {@link GenericWebApplicationContext} for AOT run-time execution based on
|
||||
* the supplied {@link MergedContextConfiguration} and
|
||||
* {@link ApplicationContextInitializer}.
|
||||
* @param mergedConfig the merged context configuration to use to load the
|
||||
* application context
|
||||
* @param initializer the {@code ApplicationContextInitializer} that should
|
||||
* be applied to the context in order to recreate bean definitions
|
||||
* @return a new web application context
|
||||
* @throws Exception if context loading failed
|
||||
* @since 6.0
|
||||
* @see AotContextLoader#loadContextForAotRuntime(MergedContextConfiguration, ApplicationContextInitializer)
|
||||
*/
|
||||
@Override
|
||||
public final GenericWebApplicationContext loadContextForAotRuntime(MergedContextConfiguration mergedConfig,
|
||||
ApplicationContextInitializer<ConfigurableApplicationContext> initializer) throws Exception {
|
||||
|
||||
Assert.notNull(mergedConfig, "MergedContextConfiguration must not be null");
|
||||
Assert.notNull(initializer, "ApplicationContextInitializer must not be null");
|
||||
if (!(mergedConfig instanceof WebMergedContextConfiguration webMergedConfig)) {
|
||||
throw new IllegalArgumentException("""
|
||||
Cannot load WebApplicationContext from non-web merged context configuration %s. \
|
||||
Consider annotating your test class with @WebAppConfiguration."""
|
||||
.formatted(mergedConfig));
|
||||
}
|
||||
|
||||
validateMergedContextConfiguration(webMergedConfig);
|
||||
|
||||
GenericWebApplicationContext context = createContext();
|
||||
configureWebResources(context, webMergedConfig);
|
||||
prepareContext(context, webMergedConfig);
|
||||
initializer.initialize(context);
|
||||
customizeContext(context, webMergedConfig);
|
||||
context.refresh();
|
||||
return context;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a {@link GenericWebApplicationContext} for the supplied
|
||||
* {@link MergedContextConfiguration}.
|
||||
* @param mergedConfig the merged context configuration to use to load the
|
||||
* application context
|
||||
* @param refresh whether to refresh the {@code ApplicationContext} and register
|
||||
* a JVM shutdown hook for it
|
||||
* @param forAotProcessing {@code true} if the context is being loaded for
|
||||
* AOT processing, meaning not to refresh the {@code ApplicationContext} or
|
||||
* 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.SmartContextLoader#loadContextForAotProcessing(MergedContextConfiguration)
|
||||
* @see org.springframework.test.context.aot.AotContextLoader#loadContextForAotProcessing(MergedContextConfiguration)
|
||||
*/
|
||||
private final GenericWebApplicationContext loadContext(
|
||||
MergedContextConfiguration mergedConfig, boolean refresh) throws Exception {
|
||||
MergedContextConfiguration mergedConfig, boolean forAotProcessing) throws Exception {
|
||||
|
||||
if (!(mergedConfig instanceof WebMergedContextConfiguration webMergedConfig)) {
|
||||
throw new IllegalArgumentException("""
|
||||
|
@ -178,8 +187,8 @@ public abstract class AbstractGenericWebContextLoader extends AbstractContextLoa
|
|||
}
|
||||
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(String.format("Loading WebApplicationContext for merged context configuration %s.",
|
||||
webMergedConfig));
|
||||
logger.debug("Loading WebApplicationContext %sfor merged context configuration %s"
|
||||
.formatted((forAotProcessing ? "for AOT processing " : ""), mergedConfig));
|
||||
}
|
||||
|
||||
validateMergedContextConfiguration(webMergedConfig);
|
||||
|
@ -197,7 +206,7 @@ public abstract class AbstractGenericWebContextLoader extends AbstractContextLoa
|
|||
AnnotationConfigUtils.registerAnnotationConfigProcessors(context);
|
||||
customizeContext(context, webMergedConfig);
|
||||
|
||||
if (refresh) {
|
||||
if (!forAotProcessing) {
|
||||
context.refresh();
|
||||
context.registerShutdownHook();
|
||||
}
|
||||
|
@ -343,8 +352,6 @@ public abstract class AbstractGenericWebContextLoader extends AbstractContextLoa
|
|||
}
|
||||
|
||||
|
||||
// ContextLoader
|
||||
|
||||
/**
|
||||
* {@code AbstractGenericWebContextLoader} should be used as a
|
||||
* {@link org.springframework.test.context.SmartContextLoader SmartContextLoader},
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2018 the original author or authors.
|
||||
* 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.
|
||||
|
@ -16,6 +16,8 @@
|
|||
|
||||
package org.springframework.test.context.web;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
|
@ -23,7 +25,6 @@ import org.springframework.context.annotation.AnnotatedBeanDefinitionReader;
|
|||
import org.springframework.test.context.ContextConfigurationAttributes;
|
||||
import org.springframework.test.context.MergedContextConfiguration;
|
||||
import org.springframework.test.context.support.AnnotationConfigContextLoaderUtils;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.web.context.support.GenericWebApplicationContext;
|
||||
|
||||
/**
|
||||
|
@ -159,7 +160,7 @@ public class AnnotationConfigWebContextLoader extends AbstractGenericWebContextL
|
|||
|
||||
Class<?>[] annotatedClasses = webMergedConfig.getClasses();
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Registering annotated classes: " + ObjectUtils.nullSafeToString(annotatedClasses));
|
||||
logger.debug("Registering annotated classes: " + Arrays.toString(annotatedClasses));
|
||||
}
|
||||
new AnnotatedBeanDefinitionReader(context).register(annotatedClasses);
|
||||
}
|
||||
|
@ -173,10 +174,11 @@ public class AnnotationConfigWebContextLoader extends AbstractGenericWebContextL
|
|||
@Override
|
||||
protected void validateMergedContextConfiguration(WebMergedContextConfiguration webMergedConfig) {
|
||||
if (webMergedConfig.hasLocations()) {
|
||||
String msg = String.format("Test class [%s] has been configured with @ContextConfiguration's 'locations' " +
|
||||
"(or 'value') attribute %s, but %s does not support resource locations.",
|
||||
webMergedConfig.getTestClass().getName(),
|
||||
ObjectUtils.nullSafeToString(webMergedConfig.getLocations()), getClass().getSimpleName());
|
||||
String msg = """
|
||||
Test class [%s] has been configured with @ContextConfiguration's 'locations' \
|
||||
(or 'value') attribute %s, but %s does not support resource locations."""
|
||||
.formatted(webMergedConfig.getTestClass().getName(),
|
||||
Arrays.toString(webMergedConfig.getLocations()), getClass().getSimpleName());
|
||||
logger.error(msg);
|
||||
throw new IllegalStateException(msg);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* 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.
|
||||
|
@ -16,9 +16,10 @@
|
|||
|
||||
package org.springframework.test.context.web;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader;
|
||||
import org.springframework.test.context.MergedContextConfiguration;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.web.context.support.GenericWebApplicationContext;
|
||||
|
||||
/**
|
||||
|
@ -65,10 +66,11 @@ public class GenericXmlWebContextLoader extends AbstractGenericWebContextLoader
|
|||
@Override
|
||||
protected void validateMergedContextConfiguration(WebMergedContextConfiguration webMergedConfig) {
|
||||
if (webMergedConfig.hasClasses()) {
|
||||
String msg = String.format(
|
||||
"Test class [%s] has been configured with @ContextConfiguration's 'classes' attribute %s, "
|
||||
+ "but %s does not support annotated classes.", webMergedConfig.getTestClass().getName(),
|
||||
ObjectUtils.nullSafeToString(webMergedConfig.getClasses()), getClass().getSimpleName());
|
||||
String msg = """
|
||||
Test class [%s] has been configured with @ContextConfiguration's 'classes' \
|
||||
attribute %s, but %s does not support annotated classes."""
|
||||
.formatted(webMergedConfig.getTestClass().getName(),
|
||||
Arrays.toString(webMergedConfig.getClasses()), getClass().getSimpleName());
|
||||
logger.error(msg);
|
||||
throw new IllegalStateException(msg);
|
||||
}
|
||||
|
|
|
@ -29,16 +29,18 @@ import org.springframework.util.ObjectUtils;
|
|||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* {@code WebMergedContextConfiguration} encapsulates the <em>merged</em>
|
||||
* context configuration declared on a test class and all of its superclasses
|
||||
* via {@link org.springframework.test.context.ContextConfiguration @ContextConfiguration},
|
||||
* {@link WebAppConfiguration @WebAppConfiguration}, and
|
||||
* {@link org.springframework.test.context.ActiveProfiles @ActiveProfiles}.
|
||||
* {@code WebMergedContextConfiguration} encapsulates the <em>merged</em> context
|
||||
* configuration declared on a test class and all of its superclasses and
|
||||
* enclosing classes via
|
||||
* {@link org.springframework.test.context.ContextConfiguration @ContextConfiguration},
|
||||
* {@link WebAppConfiguration @WebAppConfiguration},
|
||||
* {@link org.springframework.test.context.ActiveProfiles @ActiveProfiles}, and
|
||||
* {@link org.springframework.test.context.TestPropertySource @TestPropertySource}.
|
||||
*
|
||||
* <p>{@code WebMergedContextConfiguration} extends the contract of
|
||||
* {@link MergedContextConfiguration} by adding support for the {@link
|
||||
* {@link MergedContextConfiguration} by adding support for the {@linkplain
|
||||
* #getResourceBasePath() resource base path} configured via {@code @WebAppConfiguration}.
|
||||
* This allows the {@link org.springframework.test.context.TestContext TestContext}
|
||||
* This allows the {@link org.springframework.test.context.cache.ContextCache ContextCache}
|
||||
* to properly cache the corresponding {@link
|
||||
* org.springframework.web.context.WebApplicationContext WebApplicationContext}
|
||||
* that was loaded using properties of this {@code WebMergedContextConfiguration}.
|
||||
|
@ -69,7 +71,7 @@ public class WebMergedContextConfiguration extends MergedContextConfiguration {
|
|||
*/
|
||||
public WebMergedContextConfiguration(MergedContextConfiguration mergedConfig, String resourceBasePath) {
|
||||
super(mergedConfig);
|
||||
this.resourceBasePath = !StringUtils.hasText(resourceBasePath) ? "" : resourceBasePath;
|
||||
this.resourceBasePath = (StringUtils.hasText(resourceBasePath) ? resourceBasePath : "");
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
Loading…
Reference in New Issue