Browse Source

Introduce configurable refresh support in SmartContextLoader SPI

Prior to this commit, the contract of the loadContext() method in the
SmartContextLoader SPI required that the ApplicationContext be returned
in a fully refreshed state with a JVM shutdown hook registered for it.

However, in order to support AOT processing within the Spring
TestContext Framework (TCF), we need a way to signal to
SmartContextLoader implementations that they should load the test's
ApplicationContext without refreshing it or registering a JVM shutdown
hook.

To address this issue, this commit:

- Introduces a new loadContext(MergedContextConfiguration, boolean)
  method. The boolean `refresh` flag controls whether the returned
  ApplicationContext should be refreshed and have a JVM shutdown hook
  registered for it.

- Deprecates the existing loadContext(MergedContextConfiguration)
  method in favor of loadContext(MergedContextConfiguration, boolean).

- Removes all use of the deprecated method within the spring-test
  module, excluding the exception mentioned below.

Note that loadContext(MergedContextConfiguration, boolean) is
implemented as an interface `default` method which delegates to the
deprecated loadContext(MergedContextConfiguration) method for backward
compatibility. When migrating a SmartContextLoader to Spring Framework
6.0, implementations that directly implement the SmartContextLoader SPI
(instead of extending AbstractGenericContextLoader or
AbstractGenericWebContextLoader) will need to override the new
loadContext(MergedContextConfiguration, boolean) method in order to
honor the `refresh` flag for AOT processing support. See the
implementation in AbstractGenericContextLoader for an example of how
this can be achieved.

Closes gh-28906
pull/28922/head
Sam Brannen 2 years ago
parent
commit
903e9f2a02
  1. 2
      spring-test/src/main/java/org/springframework/test/context/MergedContextConfiguration.java
  2. 90
      spring-test/src/main/java/org/springframework/test/context/SmartContextLoader.java
  3. 2
      spring-test/src/main/java/org/springframework/test/context/cache/DefaultCacheAwareContextLoaderDelegate.java
  4. 2
      spring-test/src/main/java/org/springframework/test/context/support/AbstractContextLoader.java
  5. 27
      spring-test/src/main/java/org/springframework/test/context/support/AbstractDelegatingSmartContextLoader.java
  6. 57
      spring-test/src/main/java/org/springframework/test/context/support/AbstractGenericContextLoader.java
  7. 31
      spring-test/src/main/java/org/springframework/test/context/web/AbstractGenericWebContextLoader.java
  8. 4
      spring-test/src/main/java/org/springframework/test/context/web/WebMergedContextConfiguration.java
  9. 6
      spring-test/src/test/java/org/springframework/test/context/support/AnnotatedFooConfigInnerClassTestCase.java
  10. 45
      spring-test/src/test/java/org/springframework/test/context/support/AnnotationConfigContextLoaderTests.java
  11. 2
      spring-test/src/test/java/org/springframework/test/context/support/CustomizedGenericXmlContextLoaderTests.java
  12. 252
      spring-test/src/test/java/org/springframework/test/context/support/DelegatingSmartContextLoaderTests.java
  13. 4
      spring-test/src/test/java/org/springframework/test/context/support/GenericXmlContextLoaderTests.java
  14. 4
      spring-test/src/test/java/org/springframework/test/context/web/AnnotationConfigWebContextLoaderTests.java
  15. 4
      spring-test/src/test/java/org/springframework/test/context/web/GenericXmlWebContextLoaderTests.java

2
spring-test/src/main/java/org/springframework/test/context/MergedContextConfiguration.java

@ -62,7 +62,7 @@ import org.springframework.util.StringUtils; @@ -62,7 +62,7 @@ import org.springframework.util.StringUtils;
* @see ActiveProfiles
* @see TestPropertySource
* @see ContextConfigurationAttributes
* @see SmartContextLoader#loadContext(MergedContextConfiguration)
* @see SmartContextLoader#loadContext(MergedContextConfiguration, boolean)
*/
public class MergedContextConfiguration implements Serializable {

90
spring-test/src/main/java/org/springframework/test/context/SmartContextLoader.java

@ -25,34 +25,34 @@ import org.springframework.lang.Nullable; @@ -25,34 +25,34 @@ import org.springframework.lang.Nullable;
*
* <p>The {@code SmartContextLoader} SPI supersedes the {@link ContextLoader} SPI
* introduced in Spring 2.5: a {@code SmartContextLoader} can choose to process
* resource locations, annotated classes, or a combination of both. Furthermore, a
* resource locations, component classes, or a combination of both. Furthermore, a
* {@code SmartContextLoader} can configure the context that it
* {@linkplain #loadContext(MergedContextConfiguration) loads} based on any
* properties available in the provided {@link MergedContextConfiguration}. For
* example, active bean definition profiles can be configured for the context
* {@linkplain #loadContext(MergedContextConfiguration, boolean) loads} based on
* any properties available in the provided {@link MergedContextConfiguration}.
* For example, active bean definition profiles can be configured for the context
* based on {@link MergedContextConfiguration#getActiveProfiles()}.
*
* <p>See the Javadoc for {@link ContextConfiguration @ContextConfiguration}
* for a definition of <em>annotated class</em>.
* for a definition of <em>component classes</em>.
*
* <p>Clients of a {@code SmartContextLoader} should call
* {@link #processContextConfiguration(ContextConfigurationAttributes)
* processContextConfiguration()} prior to calling
* {@link #loadContext(MergedContextConfiguration) loadContext()}. This gives a
* {@code SmartContextLoader} the opportunity to provide custom support for
* modifying resource locations or detecting default resource locations or
* {@link #loadContext(MergedContextConfiguration, boolean) loadContext()}. This
* gives a {@code SmartContextLoader} the opportunity to provide custom support
* for modifying resource locations or detecting default resource locations or
* default configuration classes. The results of
* {@link #processContextConfiguration(ContextConfigurationAttributes)
* processContextConfiguration()} should be merged for all classes in the
* hierarchy of the root test class and then supplied to
* {@link #loadContext(MergedContextConfiguration) loadContext()}.
* {@link #loadContext(MergedContextConfiguration, boolean) loadContext()}.
*
* <p>NOTE: As of Spring Framework 6.0, {@code SmartContextLoader} no longer
* supports methods defined in the {@code ContextLoader} SPI.
*
* <p>Concrete implementations must provide a {@code public} no-args constructor.
*
* <p>Spring provides the following out-of-the-box implementations:
* <p>Spring provides the following {@code SmartContextLoader} implementations.
* <ul>
* <li>{@link org.springframework.test.context.support.DelegatingSmartContextLoader DelegatingSmartContextLoader}</li>
* <li>{@link org.springframework.test.context.support.AnnotationConfigContextLoader AnnotationConfigContextLoader}</li>
@ -92,10 +92,9 @@ public interface SmartContextLoader extends ContextLoader { @@ -92,10 +92,9 @@ public interface SmartContextLoader extends ContextLoader {
void processContextConfiguration(ContextConfigurationAttributes configAttributes);
/**
* Load a new {@linkplain ApplicationContext context} based on the supplied
* {@link MergedContextConfiguration merged context configuration},
* configure the context, and return the context in a fully <em>refreshed</em>
* state.
* Load a new {@link ApplicationContext} based on the supplied
* {@link MergedContextConfiguration}, configure the context, and return the
* context in a fully <em>refreshed</em> state.
* <p>Concrete implementations should register annotation configuration
* processors with bean factories of
* {@link ApplicationContext application contexts} loaded by this
@ -134,9 +133,68 @@ public interface SmartContextLoader extends ContextLoader { @@ -134,9 +133,68 @@ public interface SmartContextLoader extends ContextLoader {
* @see #processContextConfiguration(ContextConfigurationAttributes)
* @see org.springframework.context.annotation.AnnotationConfigUtils#registerAnnotationConfigProcessors(org.springframework.beans.factory.support.BeanDefinitionRegistry)
* @see org.springframework.context.ConfigurableApplicationContext#getEnvironment()
* @deprecated as of Spring Framework 6.0, in favor of {@link #loadContext(MergedContextConfiguration, boolean)}
*/
@Deprecated
ApplicationContext loadContext(MergedContextConfiguration mergedConfig) throws Exception;
/**
* Load a new {@linkplain ApplicationContext} based on the supplied
* {@link MergedContextConfiguration}, configure the context, and return the
* context.
* <p>Concrete implementations should register annotation configuration
* processors with bean factories of
* {@linkplain ApplicationContext application contexts} loaded by this
* {@code SmartContextLoader}. Beans will therefore automatically be
* candidates for annotation-based dependency injection using
* {@link org.springframework.beans.factory.annotation.Autowired @Autowired},
* {@link jakarta.annotation.Resource @Resource}, and
* {@link jakarta.inject.Inject @Inject}. In addition, concrete implementations
* should perform the following actions.
* <ul>
* <li>Set the parent {@code ApplicationContext} if appropriate (see
* {@link MergedContextConfiguration#getParent()}).</li>
* <li>Set the active bean definition profiles in the context's
* {@link org.springframework.core.env.Environment Environment} (see
* {@link MergedContextConfiguration#getActiveProfiles()}).</li>
* <li>Add test {@link org.springframework.core.env.PropertySource PropertySources}
* to the {@code Environment} (see
* {@link MergedContextConfiguration#getPropertySourceLocations()},
* {@link MergedContextConfiguration#getPropertySourceProperties()}, and
* {@link org.springframework.test.context.support.TestPropertySourceUtils
* TestPropertySourceUtils}).</li>
* <li>Invoke {@link org.springframework.context.ApplicationContextInitializer
* ApplicationContextInitializers} (see
* {@link MergedContextConfiguration#getContextInitializerClasses()}).</li>
* <li>Invoke {@link ContextCustomizer ContextCustomizers} (see
* {@link MergedContextConfiguration#getContextCustomizers()}).</li>
* <li>If the supplied {@code refresh} flag is {@code true},
* {@linkplain org.springframework.context.ConfigurableApplicationContext#refresh()
* refresh} the {@code ApplicationContext} and
* {@linkplain org.springframework.context.ConfigurableApplicationContext#registerShutdownHook()
* register a JVM shutdown hook} for it.</li>
* </ul>
* <p>The default implementation delegates to {@link #loadContext(MergedContextConfiguration)}
* for backward compatibility. Concrete implementations should therefore
* override this method in order to honor the {@code refresh} flag which is
* required for AOT (ahead of time) processing support.
* @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
* @return a new application context
* @throws Exception if context loading failed
* @since 6.0
* @see #processContextConfiguration(ContextConfigurationAttributes)
* @see org.springframework.context.annotation.AnnotationConfigUtils#registerAnnotationConfigProcessors(org.springframework.beans.factory.support.BeanDefinitionRegistry)
* @see org.springframework.context.ConfigurableApplicationContext#getEnvironment()
* @see org.springframework.context.ConfigurableApplicationContext#registerShutdownHook()
*/
@SuppressWarnings("deprecation")
default ApplicationContext loadContext(MergedContextConfiguration mergedConfig, boolean refresh) throws Exception {
return loadContext(mergedConfig);
}
/**
* {@code SmartContextLoader} does not support deprecated {@link ContextLoader} methods.
* Call {@link #processContextConfiguration(ContextConfigurationAttributes)} instead.
@ -153,7 +211,7 @@ public interface SmartContextLoader extends ContextLoader { @@ -153,7 +211,7 @@ public interface SmartContextLoader extends ContextLoader {
/**
* {@code SmartContextLoader} does not support deprecated {@link ContextLoader} methods.
* <p>Call {@link #loadContext(MergedContextConfiguration)} instead.
* <p>Call {@link #loadContext(MergedContextConfiguration, boolean)} instead.
* @throws UnsupportedOperationException in this implementation
* @since 6.0
*/
@ -162,7 +220,7 @@ public interface SmartContextLoader extends ContextLoader { @@ -162,7 +220,7 @@ public interface SmartContextLoader extends ContextLoader {
default ApplicationContext loadContext(String... locations) throws Exception {
throw new UnsupportedOperationException("""
SmartContextLoader does not support the ContextLoader SPI. \
Call loadContext(MergedContextConfiguration) instead.""");
Call loadContext(MergedContextConfiguration, boolean) instead.""");
}
}

2
spring-test/src/main/java/org/springframework/test/context/cache/DefaultCacheAwareContextLoaderDelegate.java vendored

@ -96,7 +96,7 @@ public class DefaultCacheAwareContextLoaderDelegate implements CacheAwareContext @@ -96,7 +96,7 @@ public class DefaultCacheAwareContextLoaderDelegate implements CacheAwareContext
ApplicationContext applicationContext;
if (contextLoader instanceof SmartContextLoader smartContextLoader) {
applicationContext = smartContextLoader.loadContext(mergedContextConfiguration);
applicationContext = smartContextLoader.loadContext(mergedContextConfiguration, true);
}
else {
String[] locations = mergedContextConfiguration.getLocations();

2
spring-test/src/main/java/org/springframework/test/context/support/AbstractContextLoader.java

@ -128,7 +128,7 @@ public abstract class AbstractContextLoader implements SmartContextLoader { @@ -128,7 +128,7 @@ public abstract class AbstractContextLoader implements SmartContextLoader {
* @see TestPropertySourceUtils#addPropertiesFilesToEnvironment
* @see TestPropertySourceUtils#addInlinedPropertiesToEnvironment
* @see ApplicationContextInitializer#initialize(ConfigurableApplicationContext)
* @see #loadContext(MergedContextConfiguration)
* @see #loadContext(MergedContextConfiguration, boolean)
* @see ConfigurableApplicationContext#setId
*/
protected void prepareContext(ConfigurableApplicationContext context, MergedContextConfiguration mergedConfig) {

27
spring-test/src/main/java/org/springframework/test/context/support/AbstractDelegatingSmartContextLoader.java

@ -175,6 +175,18 @@ public abstract class AbstractDelegatingSmartContextLoader implements SmartConte @@ -175,6 +175,18 @@ public abstract class AbstractDelegatingSmartContextLoader implements SmartConte
}
}
/**
* Although this method is officially deprecated, for backward compatibility
* it delegates to {@link #loadContext(MergedContextConfiguration, boolean)},
* supplying {@code true} for the {@code refresh} flag.
* @deprecated as of Spring Framework 6.0, in favor of {@link #loadContext(MergedContextConfiguration, boolean)}
*/
@Override
@Deprecated
public final ApplicationContext loadContext(MergedContextConfiguration mergedConfig) throws Exception {
return loadContext(mergedConfig, true);
}
/**
* Delegates to an appropriate candidate {@code SmartContextLoader} to load
* an {@link ApplicationContext}.
@ -191,12 +203,16 @@ public abstract class AbstractDelegatingSmartContextLoader implements SmartConte @@ -191,12 +203,16 @@ public abstract class AbstractDelegatingSmartContextLoader implements SmartConte
* the annotation-based loader will load the {@code ApplicationContext}.</li>
* </ul>
* @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
* @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
*/
@Override
public ApplicationContext loadContext(MergedContextConfiguration mergedConfig) throws Exception {
public ApplicationContext loadContext(MergedContextConfiguration mergedConfig, boolean refresh) throws Exception {
Assert.notNull(mergedConfig, "MergedContextConfiguration must not be null");
Assert.state(!(mergedConfig.hasLocations() && mergedConfig.hasClasses()), () -> String.format(
@ -209,7 +225,7 @@ public abstract class AbstractDelegatingSmartContextLoader implements SmartConte @@ -209,7 +225,7 @@ public abstract class AbstractDelegatingSmartContextLoader implements SmartConte
// 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);
return delegateLoading(loader, mergedConfig, refresh);
}
}
@ -217,7 +233,7 @@ public abstract class AbstractDelegatingSmartContextLoader implements SmartConte @@ -217,7 +233,7 @@ public abstract class AbstractDelegatingSmartContextLoader implements SmartConte
// ACIs or customizers were declared, then delegate to the annotation config
// loader.
if (!mergedConfig.getContextInitializerClasses().isEmpty() || !mergedConfig.getContextCustomizers().isEmpty()) {
return delegateLoading(getAnnotationConfigLoader(), mergedConfig);
return delegateLoading(getAnnotationConfigLoader(), mergedConfig, refresh);
}
// else...
@ -235,13 +251,14 @@ public abstract class AbstractDelegatingSmartContextLoader implements SmartConte @@ -235,13 +251,14 @@ public abstract class AbstractDelegatingSmartContextLoader implements SmartConte
loader.processContextConfiguration(configAttributes);
}
private static ApplicationContext delegateLoading(SmartContextLoader loader, MergedContextConfiguration mergedConfig)
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 from %s.", name(loader), mergedConfig));
}
return loader.loadContext(mergedConfig);
return loader.loadContext(mergedConfig, refresh);
}
private boolean supports(SmartContextLoader loader, MergedContextConfiguration mergedConfig) {

57
spring-test/src/main/java/org/springframework/test/context/support/AbstractGenericContextLoader.java

@ -1,5 +1,5 @@ @@ -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.
@ -40,9 +40,9 @@ import org.springframework.util.StringUtils; @@ -40,9 +40,9 @@ import org.springframework.util.StringUtils;
* <li>If instances of concrete subclasses are invoked via the
* {@link org.springframework.test.context.SmartContextLoader SmartContextLoader}
* SPI, the context will be loaded from the {@link MergedContextConfiguration}
* provided to {@link #loadContext(MergedContextConfiguration)}. In such cases, a
* {@code SmartContextLoader} will decide whether to load the context from
* <em>locations</em> or <em>annotated classes</em>.</li>
* provided to {@link #loadContext(MergedContextConfiguration, boolean)}. In such
* cases, a {@code SmartContextLoader} will decide whether to load the context
* from <em>locations</em> or <em>annotated classes</em>.</li>
* </ul>
*
* <p>Concrete subclasses must provide an appropriate implementation of
@ -54,13 +54,23 @@ import org.springframework.util.StringUtils; @@ -54,13 +54,23 @@ import org.springframework.util.StringUtils;
* @author Juergen Hoeller
* @author Phillip Webb
* @since 2.5
* @see #loadContext(MergedContextConfiguration)
* @see #loadContext(String...)
* @see #loadContext(MergedContextConfiguration, boolean)
*/
public abstract class AbstractGenericContextLoader extends AbstractContextLoader {
protected static final Log logger = LogFactory.getLog(AbstractGenericContextLoader.class);
/**
* Although this method is officially deprecated, for backward compatibility
* it delegates to {@link #loadContext(MergedContextConfiguration, boolean)},
* supplying {@code true} for the {@code refresh} flag.
* @deprecated as of Spring Framework 6.0, in favor of {@link #loadContext(MergedContextConfiguration, boolean)}
*/
@Override
@Deprecated
public final ApplicationContext loadContext(MergedContextConfiguration mergedConfig) throws Exception {
return loadContext(mergedConfig, true);
}
/**
* Load a Spring ApplicationContext from the supplied {@link MergedContextConfiguration}.
@ -94,15 +104,22 @@ public abstract class AbstractGenericContextLoader extends AbstractContextLoader @@ -94,15 +104,22 @@ public abstract class AbstractGenericContextLoader extends AbstractContextLoader
* <li>Calls {@link #customizeContext(ConfigurableApplicationContext, MergedContextConfiguration)} to
* allow for customizing the context before it is refreshed.</li>
* <li>{@link ConfigurableApplicationContext#refresh Refreshes} the
* context and registers a JVM shutdown hook for it.</li>
* context and registers a JVM shutdown hook for it if the supplied the
* {@code refresh} flag is {@code true}.</li>
* </ul>
* @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
* @return a new application context
* @since 3.1
* @see org.springframework.test.context.SmartContextLoader#loadContext(MergedContextConfiguration)
* @since 6.0
* @see org.springframework.test.context.SmartContextLoader#loadContext(MergedContextConfiguration, boolean)
* @see GenericApplicationContext
*/
@Override
public final ConfigurableApplicationContext loadContext(MergedContextConfiguration mergedConfig) throws Exception {
public final ConfigurableApplicationContext loadContext(
MergedContextConfiguration mergedConfig, boolean refresh) throws Exception {
if (logger.isDebugEnabled()) {
logger.debug(String.format("Loading ApplicationContext for merged context configuration [%s].",
mergedConfig));
@ -124,8 +141,10 @@ public abstract class AbstractGenericContextLoader extends AbstractContextLoader @@ -124,8 +141,10 @@ public abstract class AbstractGenericContextLoader extends AbstractContextLoader
customizeContext(context);
customizeContext(context, mergedConfig);
context.refresh();
context.registerShutdownHook();
if (refresh) {
context.refresh();
context.registerShutdownHook();
}
return context;
}
@ -166,15 +185,15 @@ public abstract class AbstractGenericContextLoader extends AbstractContextLoader @@ -166,15 +185,15 @@ public abstract class AbstractGenericContextLoader extends AbstractContextLoader
* context and registers a JVM shutdown hook for it.</li>
* </ul>
* <p><b>Note</b>: this method does not provide a means to set active bean definition
* profiles for the loaded context. See {@link #loadContext(MergedContextConfiguration)}
* profiles for the loaded context. See {@link #loadContext(MergedContextConfiguration, boolean)}
* and {@link AbstractContextLoader#prepareContext(ConfigurableApplicationContext, MergedContextConfiguration)}
* for an alternative.
* @return a new application context
* @since 2.5
* @see org.springframework.test.context.ContextLoader#loadContext
* @see GenericApplicationContext
* @see #loadContext(MergedContextConfiguration)
* @deprecated as of Spring Framework 6.0, in favor of {@link #loadContext(MergedContextConfiguration)}
* @see #loadContext(MergedContextConfiguration, boolean)
* @deprecated as of Spring Framework 6.0, in favor of {@link #loadContext(MergedContextConfiguration, boolean)}
*/
@Deprecated
@Override
@ -219,7 +238,7 @@ public abstract class AbstractGenericContextLoader extends AbstractContextLoader @@ -219,7 +238,7 @@ public abstract class AbstractGenericContextLoader extends AbstractContextLoader
* customize {@code GenericApplicationContext}'s standard settings.
* @param context the context that should be prepared
* @since 2.5
* @see #loadContext(MergedContextConfiguration)
* @see #loadContext(MergedContextConfiguration, boolean)
* @see #loadContext(String...)
* @see GenericApplicationContext#setAllowBeanDefinitionOverriding
* @see GenericApplicationContext#setResourceLoader
@ -236,7 +255,7 @@ public abstract class AbstractGenericContextLoader extends AbstractContextLoader @@ -236,7 +255,7 @@ public abstract class AbstractGenericContextLoader extends AbstractContextLoader
* to customize {@code DefaultListableBeanFactory}'s standard settings.
* @param beanFactory the bean factory created by this {@code ContextLoader}
* @since 2.5
* @see #loadContext(MergedContextConfiguration)
* @see #loadContext(MergedContextConfiguration, boolean)
* @see #loadContext(String...)
* @see DefaultListableBeanFactory#setAllowBeanDefinitionOverriding
* @see DefaultListableBeanFactory#setAllowEagerClassLoading
@ -261,7 +280,7 @@ public abstract class AbstractGenericContextLoader extends AbstractContextLoader @@ -261,7 +280,7 @@ public abstract class AbstractGenericContextLoader extends AbstractContextLoader
* @param context the context into which the bean definitions should be loaded
* @param mergedConfig the merged context configuration
* @since 3.1
* @see #loadContext(MergedContextConfiguration)
* @see #loadContext(MergedContextConfiguration, boolean)
*/
protected void loadBeanDefinitions(GenericApplicationContext context, MergedContextConfiguration mergedConfig) {
createBeanDefinitionReader(context).loadBeanDefinitions(mergedConfig.getLocations());
@ -288,7 +307,7 @@ public abstract class AbstractGenericContextLoader extends AbstractContextLoader @@ -288,7 +307,7 @@ public abstract class AbstractGenericContextLoader extends AbstractContextLoader
* to customize the application context.
* @param context the newly created application context
* @since 2.5
* @see #loadContext(MergedContextConfiguration)
* @see #loadContext(MergedContextConfiguration, boolean)
* @see #loadContext(String...)
* @see #customizeContext(ConfigurableApplicationContext, MergedContextConfiguration)
*/

31
spring-test/src/main/java/org/springframework/test/context/web/AbstractGenericWebContextLoader.java

@ -64,6 +64,18 @@ public abstract class AbstractGenericWebContextLoader extends AbstractContextLoa @@ -64,6 +64,18 @@ public abstract class AbstractGenericWebContextLoader extends AbstractContextLoa
// SmartContextLoader
/**
* Although this method is officially deprecated, for backward compatibility
* it delegates to {@link #loadContext(MergedContextConfiguration, boolean)},
* supplying {@code true} for the {@code refresh} flag.
* @deprecated as of Spring Framework 6.0, in favor of {@link #loadContext(MergedContextConfiguration, boolean)}
*/
@Override
@Deprecated
public final ApplicationContext loadContext(MergedContextConfiguration mergedConfig) throws Exception {
return loadContext(mergedConfig, true);
}
/**
* Load a Spring {@link WebApplicationContext} from the supplied
* {@link MergedContextConfiguration}.
@ -94,12 +106,19 @@ public abstract class AbstractGenericWebContextLoader extends AbstractContextLoa @@ -94,12 +106,19 @@ public abstract class AbstractGenericWebContextLoader extends AbstractContextLoa
* <li>{@link ConfigurableApplicationContext#refresh Refreshes} the
* context and registers a JVM shutdown hook for it.</li>
* </ul>
* @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
* @return a new web application context
* @see org.springframework.test.context.SmartContextLoader#loadContext(MergedContextConfiguration)
* @since 6.0
* @see org.springframework.test.context.SmartContextLoader#loadContext(MergedContextConfiguration, boolean)
* @see GenericWebApplicationContext
*/
@Override
public final ConfigurableApplicationContext loadContext(MergedContextConfiguration mergedConfig) throws Exception {
public final ConfigurableApplicationContext loadContext(
MergedContextConfiguration mergedConfig, boolean refresh) throws Exception {
Assert.isTrue(mergedConfig instanceof WebMergedContextConfiguration,
() -> String.format("Cannot load WebApplicationContext from non-web merged context configuration %s. " +
"Consider annotating your test class with @WebAppConfiguration.", mergedConfig));
@ -125,8 +144,12 @@ public abstract class AbstractGenericWebContextLoader extends AbstractContextLoa @@ -125,8 +144,12 @@ public abstract class AbstractGenericWebContextLoader extends AbstractContextLoa
loadBeanDefinitions(context, webMergedConfig);
AnnotationConfigUtils.registerAnnotationConfigProcessors(context);
customizeContext(context, webMergedConfig);
context.refresh();
context.registerShutdownHook();
if (refresh) {
context.refresh();
context.registerShutdownHook();
}
return context;
}

4
spring-test/src/main/java/org/springframework/test/context/web/WebMergedContextConfiguration.java

@ -1,5 +1,5 @@ @@ -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.
@ -50,7 +50,7 @@ import org.springframework.util.StringUtils; @@ -50,7 +50,7 @@ import org.springframework.util.StringUtils;
* @see org.springframework.test.context.ContextConfiguration
* @see org.springframework.test.context.ActiveProfiles
* @see org.springframework.test.context.ContextConfigurationAttributes
* @see org.springframework.test.context.SmartContextLoader#loadContext(MergedContextConfiguration)
* @see org.springframework.test.context.SmartContextLoader#loadContext(MergedContextConfiguration, boolean)
*/
public class WebMergedContextConfiguration extends MergedContextConfiguration {

6
spring-test/src/test/java/org/springframework/test/context/support/AnnotatedFooConfigInnerClassTestCase.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2012 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.
@ -28,11 +28,11 @@ import org.springframework.context.annotation.Configuration; @@ -28,11 +28,11 @@ import org.springframework.context.annotation.Configuration;
*/
public class AnnotatedFooConfigInnerClassTestCase {
@Configuration
@Configuration(proxyBeanMethods = false)
static class FooConfig {
@Bean
public String foo() {
String foo() {
return "foo";
}
}

45
spring-test/src/test/java/org/springframework/test/context/support/AnnotationConfigContextLoaderTests.java

@ -1,5 +1,5 @@ @@ -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,8 +16,11 @@ @@ -16,8 +16,11 @@
package org.springframework.test.context.support;
import java.util.Arrays;
import org.junit.jupiter.api.Test;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.test.context.MergedContextConfiguration;
import static org.assertj.core.api.Assertions.assertThat;
@ -31,24 +34,54 @@ import static org.assertj.core.api.Assertions.assertThatIllegalStateException; @@ -31,24 +34,54 @@ import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
*/
class AnnotationConfigContextLoaderTests {
private final AnnotationConfigContextLoader contextLoader = new AnnotationConfigContextLoader();
private static final String[] EMPTY_STRING_ARRAY = new String[0];
private static final Class<?>[] EMPTY_CLASS_ARRAY = new Class<?>[0];
private final AnnotationConfigContextLoader contextLoader = new AnnotationConfigContextLoader();
/**
* @since 4.0.4
*/
@Test
void configMustNotContainLocations() throws Exception {
void loadContextWithConfigContainingLocationsResultsInException() {
MergedContextConfiguration mergedConfig = new MergedContextConfiguration(getClass(),
new String[] { "config.xml" }, EMPTY_CLASS_ARRAY, EMPTY_STRING_ARRAY, contextLoader);
assertThatIllegalStateException().isThrownBy(() ->
contextLoader.loadContext(mergedConfig))
assertThatIllegalStateException()
.isThrownBy(() -> contextLoader.loadContext(mergedConfig, true))
.withMessageContaining("does not support resource locations");
}
/**
* @since 6.0
*/
@Test
void loadContextHonorsRefreshTrue() throws Exception {
MergedContextConfiguration mergedConfig = new MergedContextConfiguration(
AnnotatedFooConfigInnerClassTestCase.class, EMPTY_STRING_ARRAY,
new Class<?>[] {AnnotatedFooConfigInnerClassTestCase.FooConfig.class},
EMPTY_STRING_ARRAY, contextLoader);
ConfigurableApplicationContext context = contextLoader.loadContext(mergedConfig, true);
assertThat(context).isNotNull();
assertThat(context.isActive()).as("ApplicationContext is active").isTrue();
assertThat(context.getBean(String.class)).isEqualTo("foo");
}
/**
* @since 6.0
*/
@Test
void loadContextHonorsRefreshFalse() throws Exception {
MergedContextConfiguration mergedConfig = new MergedContextConfiguration(
AnnotatedFooConfigInnerClassTestCase.class, EMPTY_STRING_ARRAY,
new Class<?>[] {AnnotatedFooConfigInnerClassTestCase.FooConfig.class},
EMPTY_STRING_ARRAY, contextLoader);
ConfigurableApplicationContext context = contextLoader.loadContext(mergedConfig, false);
assertThat(context).isNotNull();
assertThat(context.isActive()).as("ApplicationContext is active").isFalse();
assertThat(Arrays.stream(context.getBeanDefinitionNames())).anyMatch(name -> name.contains("FooConfig"));
}
@Test
void detectDefaultConfigurationClassesForAnnotatedInnerClass() {
Class<?>[] configClasses = contextLoader.detectDefaultConfigurationClasses(ContextConfigurationInnerClassTestCase.class);

2
spring-test/src/test/java/org/springframework/test/context/support/CustomizedGenericXmlContextLoaderTests.java

@ -53,7 +53,7 @@ class CustomizedGenericXmlContextLoaderTests { @@ -53,7 +53,7 @@ class CustomizedGenericXmlContextLoaderTests {
MergedContextConfiguration mergedConfig =
new MergedContextConfiguration(getClass(), null, null, null, null);
customLoader.loadContext(mergedConfig);
customLoader.loadContext(mergedConfig, true);
assertThat(customizeInvoked).as("customizeContext() should have been invoked").isTrue();
}

252
spring-test/src/test/java/org/springframework/test/context/support/DelegatingSmartContextLoaderTests.java

@ -16,6 +16,9 @@ @@ -16,6 +16,9 @@
package org.springframework.test.context.support;
import java.util.Arrays;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test;
import org.springframework.context.ApplicationContext;
@ -25,7 +28,6 @@ import org.springframework.context.annotation.Configuration; @@ -25,7 +28,6 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.ContextConfigurationAttributes;
import org.springframework.test.context.ContextLoader;
import org.springframework.test.context.MergedContextConfiguration;
import org.springframework.util.ObjectUtils;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
@ -45,135 +47,167 @@ class DelegatingSmartContextLoaderTests { @@ -45,135 +47,167 @@ class DelegatingSmartContextLoaderTests {
private final DelegatingSmartContextLoader loader = new DelegatingSmartContextLoader();
@Nested
class SmartContextLoaderSpiTests {
private static void assertEmpty(Object[] array) {
assertThat(ObjectUtils.isEmpty(array)).isTrue();
}
@Test
void processContextConfigurationWithDefaultXmlConfigGeneration() {
ContextConfigurationAttributes configAttributes = new ContextConfigurationAttributes(
XmlTestCase.class, EMPTY_STRING_ARRAY, EMPTY_CLASS_ARRAY, true, null, true, ContextLoader.class);
loader.processContextConfiguration(configAttributes);
assertThat(configAttributes.getLocations()).hasSize(1);
assertThat(configAttributes.getClasses()).isEmpty();
}
// --- SmartContextLoader - processContextConfiguration() ------------------
@Test
void processContextConfigurationWithDefaultConfigurationClassGeneration() {
ContextConfigurationAttributes configAttributes = new ContextConfigurationAttributes(
ConfigClassTestCase.class, EMPTY_STRING_ARRAY, EMPTY_CLASS_ARRAY, true, null, true, ContextLoader.class);
loader.processContextConfiguration(configAttributes);
assertThat(configAttributes.getClasses()).hasSize(1);
assertThat(configAttributes.getLocations()).isEmpty();
}
@Test
void processContextConfigurationWithDefaultXmlConfigGeneration() {
ContextConfigurationAttributes configAttributes = new ContextConfigurationAttributes(
XmlTestCase.class, EMPTY_STRING_ARRAY, EMPTY_CLASS_ARRAY, true, null, true, ContextLoader.class);
loader.processContextConfiguration(configAttributes);
assertThat(configAttributes.getLocations().length).isEqualTo(1);
assertEmpty(configAttributes.getClasses());
}
@Test
void processContextConfigurationWithDefaultXmlConfigAndConfigurationClassGeneration() {
ContextConfigurationAttributes configAttributes = new ContextConfigurationAttributes(
ImproperDuplicateDefaultXmlAndConfigClassTestCase.class, EMPTY_STRING_ARRAY, EMPTY_CLASS_ARRAY,
true, null, true, ContextLoader.class);
assertThatIllegalStateException()
.isThrownBy(() -> loader.processContextConfiguration(configAttributes))
.withMessageContaining("both default locations AND default configuration classes were detected");
}
@Test
void processContextConfigurationWithDefaultConfigurationClassGeneration() {
ContextConfigurationAttributes configAttributes = new ContextConfigurationAttributes(
ConfigClassTestCase.class, EMPTY_STRING_ARRAY, EMPTY_CLASS_ARRAY, true, null, true, ContextLoader.class);
loader.processContextConfiguration(configAttributes);
assertThat(configAttributes.getClasses().length).isEqualTo(1);
assertEmpty(configAttributes.getLocations());
}
@Test
void processContextConfigurationWithLocation() {
String[] locations = new String[] {"classpath:/foo.xml"};
ContextConfigurationAttributes configAttributes = new ContextConfigurationAttributes(
getClass(), locations, EMPTY_CLASS_ARRAY, true, null, true, ContextLoader.class);
loader.processContextConfiguration(configAttributes);
assertThat(configAttributes.getLocations()).isEqualTo(locations);
assertThat(configAttributes.getClasses()).isEmpty();
}
@Test
void processContextConfigurationWithDefaultXmlConfigAndConfigurationClassGeneration() {
ContextConfigurationAttributes configAttributes = new ContextConfigurationAttributes(
ImproperDuplicateDefaultXmlAndConfigClassTestCase.class, EMPTY_STRING_ARRAY, EMPTY_CLASS_ARRAY,
true, null, true, ContextLoader.class);
assertThatIllegalStateException().isThrownBy(() ->
loader.processContextConfiguration(configAttributes))
.withMessageContaining("both default locations AND default configuration classes were detected");
}
@Test
void processContextConfigurationWithConfigurationClass() {
Class<?>[] classes = new Class<?>[] {getClass()};
ContextConfigurationAttributes configAttributes = new ContextConfigurationAttributes(
getClass(), EMPTY_STRING_ARRAY, classes, true, null, true, ContextLoader.class);
loader.processContextConfiguration(configAttributes);
assertThat(configAttributes.getClasses()).isEqualTo(classes);
assertThat(configAttributes.getLocations()).isEmpty();
}
@Test
void processContextConfigurationWithLocation() {
String[] locations = new String[] {"classpath:/foo.xml"};
ContextConfigurationAttributes configAttributes = new ContextConfigurationAttributes(
getClass(), locations, EMPTY_CLASS_ARRAY, true, null, true, ContextLoader.class);
loader.processContextConfiguration(configAttributes);
assertThat(configAttributes.getLocations()).isEqualTo(locations);
assertEmpty(configAttributes.getClasses());
}
@Test
void loadContextWithNullConfig() throws Exception {
assertThatIllegalArgumentException().isThrownBy(() -> loader.loadContext(null, true));
}
@Test
void processContextConfigurationWithConfigurationClass() {
Class<?>[] classes = new Class<?>[] {getClass()};
ContextConfigurationAttributes configAttributes = new ContextConfigurationAttributes(
getClass(), EMPTY_STRING_ARRAY, classes, true, null, true, ContextLoader.class);
loader.processContextConfiguration(configAttributes);
assertThat(configAttributes.getClasses()).isEqualTo(classes);
assertEmpty(configAttributes.getLocations());
}
@Test
void loadContextWithoutLocationsAndConfigurationClasses() throws Exception {
MergedContextConfiguration mergedConfig = new MergedContextConfiguration(
getClass(), EMPTY_STRING_ARRAY, EMPTY_CLASS_ARRAY, EMPTY_STRING_ARRAY, loader);
assertThatIllegalStateException()
.isThrownBy(() -> loader.loadContext(mergedConfig, true))
.withMessageStartingWith("Neither")
.withMessageContaining("was able to load an ApplicationContext from");
}
// --- SmartContextLoader - loadContext() ----------------------------------
/**
* @since 4.1
*/
@Test
void loadContextWithLocationsAndConfigurationClasses() throws Exception {
MergedContextConfiguration mergedConfig = new MergedContextConfiguration(getClass(),
new String[] {"test.xml"}, new Class<?>[] {getClass()}, EMPTY_STRING_ARRAY, loader);
assertThatIllegalStateException()
.isThrownBy(() -> loader.loadContext(mergedConfig, true))
.withMessageStartingWith("Neither")
.withMessageContaining("declare either 'locations' or 'classes' but not both.");
}
@Test
void loadContextWithNullConfig() throws Exception {
assertThatIllegalArgumentException().isThrownBy(() ->
loader.loadContext((MergedContextConfiguration) null));
}
@Test
void loadContextWithXmlConfig() throws Exception {
MergedContextConfiguration mergedConfig = new MergedContextConfiguration(
XmlTestCase.class,
new String[] {"classpath:/org/springframework/test/context/support/DelegatingSmartContextLoaderTests$XmlTestCase-context.xml"},
EMPTY_CLASS_ARRAY, EMPTY_STRING_ARRAY, loader);
@Test
void loadContextWithoutLocationsAndConfigurationClasses() throws Exception {
MergedContextConfiguration mergedConfig = new MergedContextConfiguration(
getClass(), EMPTY_STRING_ARRAY, EMPTY_CLASS_ARRAY, EMPTY_STRING_ARRAY, loader);
assertThatIllegalStateException().isThrownBy(() ->
loader.loadContext(mergedConfig))
.withMessageStartingWith("Neither")
.withMessageContaining("was able to load an ApplicationContext from");
}
assertApplicationContextLoadsAndContainsFooString(mergedConfig);
}
/**
* @since 4.1
*/
@Test
void loadContextWithLocationsAndConfigurationClasses() throws Exception {
MergedContextConfiguration mergedConfig = new MergedContextConfiguration(getClass(),
new String[] {"test.xml"}, new Class<?>[] {getClass()}, EMPTY_STRING_ARRAY, loader);
assertThatIllegalStateException().isThrownBy(() ->
loader.loadContext(mergedConfig))
.withMessageStartingWith("Neither")
.withMessageContaining("declare either 'locations' or 'classes' but not both.");
}
@Test
void loadContextWithConfigurationClass() throws Exception {
MergedContextConfiguration mergedConfig = new MergedContextConfiguration(ConfigClassTestCase.class,
EMPTY_STRING_ARRAY, new Class<?>[] {ConfigClassTestCase.Config.class}, EMPTY_STRING_ARRAY, loader);
private void assertApplicationContextLoadsAndContainsFooString(MergedContextConfiguration mergedConfig)
throws Exception {
assertApplicationContextLoadsAndContainsFooString(mergedConfig);
}
ApplicationContext applicationContext = loader.loadContext(mergedConfig);
assertThat(applicationContext).isNotNull();
assertThat(applicationContext.getBean(String.class)).isEqualTo("foo");
boolean condition = applicationContext instanceof ConfigurableApplicationContext;
assertThat(condition).isTrue();
((ConfigurableApplicationContext) applicationContext).close();
}
private void assertApplicationContextLoadsAndContainsFooString(MergedContextConfiguration mergedConfig)
throws Exception {
@Test
void loadContextWithXmlConfig() throws Exception {
MergedContextConfiguration mergedConfig = new MergedContextConfiguration(
XmlTestCase.class,
new String[] {"classpath:/org/springframework/test/context/support/DelegatingSmartContextLoaderTests$XmlTestCase-context.xml"},
EMPTY_CLASS_ARRAY, EMPTY_STRING_ARRAY, loader);
assertApplicationContextLoadsAndContainsFooString(mergedConfig);
}
ApplicationContext applicationContext = loader.loadContext(mergedConfig, true);
assertThat(applicationContext).isInstanceOf(ConfigurableApplicationContext.class);
assertThat(applicationContext.getBean(String.class)).isEqualTo("foo");
ConfigurableApplicationContext cac = (ConfigurableApplicationContext) applicationContext;
cac.close();
}
@Test
void loadContextWithConfigurationClass() throws Exception {
MergedContextConfiguration mergedConfig = new MergedContextConfiguration(ConfigClassTestCase.class,
EMPTY_STRING_ARRAY, new Class<?>[] {ConfigClassTestCase.Config.class}, EMPTY_STRING_ARRAY, loader);
assertApplicationContextLoadsAndContainsFooString(mergedConfig);
}
/**
* @since 6.0
*/
@Test
void loadContextWithXmlConfigWithoutRefresh() throws Exception {
MergedContextConfiguration mergedConfig = new MergedContextConfiguration(
XmlTestCase.class,
new String[] {"classpath:/org/springframework/test/context/support/DelegatingSmartContextLoaderTests$XmlTestCase-context.xml"},
EMPTY_CLASS_ARRAY, EMPTY_STRING_ARRAY, loader);
assertApplicationContextLoadsWithoutRefresh(mergedConfig, "foo");
}
// --- ContextLoader -------------------------------------------------------
/**
* @since 6.0
*/
@Test
void loadContextWithConfigurationClassWithoutRefresh() throws Exception {
MergedContextConfiguration mergedConfig = new MergedContextConfiguration(ConfigClassTestCase.class,
EMPTY_STRING_ARRAY, new Class<?>[] {ConfigClassTestCase.Config.class}, EMPTY_STRING_ARRAY, loader);
@Test
void processLocations() {
assertThatExceptionOfType(UnsupportedOperationException.class).isThrownBy(() ->
loader.processLocations(getClass(), EMPTY_STRING_ARRAY));
}
assertApplicationContextLoadsWithoutRefresh(mergedConfig, "ConfigClassTestCase.Config");
}
private void assertApplicationContextLoadsWithoutRefresh(MergedContextConfiguration mergedConfig,
String expectedBeanDefName) throws Exception {
ApplicationContext context = loader.loadContext(mergedConfig, false);
assertThat(context).isInstanceOf(ConfigurableApplicationContext.class);
ConfigurableApplicationContext cac = (ConfigurableApplicationContext) context;
assertThat(cac.isActive()).as("ApplicationContext is active").isFalse();
assertThat(Arrays.stream(context.getBeanDefinitionNames())).anyMatch(name -> name.contains(expectedBeanDefName));
cac.close();
}
@Test
void loadContextFromLocations() {
assertThatExceptionOfType(UnsupportedOperationException.class).isThrownBy(() ->
loader.loadContext(EMPTY_STRING_ARRAY));
}
@Nested
class ContextLoaderSpiTests {
@Test
void processLocations() {
assertThatExceptionOfType(UnsupportedOperationException.class)
.isThrownBy(() -> loader.processLocations(getClass(), EMPTY_STRING_ARRAY));
}
@Test
void loadContextFromLocations() {
assertThatExceptionOfType(UnsupportedOperationException.class)
.isThrownBy(() -> loader.loadContext(EMPTY_STRING_ARRAY));
}
}
// -------------------------------------------------------------------------
static class XmlTestCase {
}

4
spring-test/src/test/java/org/springframework/test/context/support/GenericXmlContextLoaderTests.java

@ -1,5 +1,5 @@ @@ -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.
@ -40,7 +40,7 @@ class GenericXmlContextLoaderTests { @@ -40,7 +40,7 @@ class GenericXmlContextLoaderTests {
MergedContextConfiguration mergedConfig = new MergedContextConfiguration(getClass(), EMPTY_STRING_ARRAY,
new Class<?>[] { getClass() }, EMPTY_STRING_ARRAY, loader);
assertThatIllegalStateException()
.isThrownBy(() -> loader.loadContext(mergedConfig))
.isThrownBy(() -> loader.loadContext(mergedConfig, true))
.withMessageContaining("does not support annotated classes");
}

4
spring-test/src/test/java/org/springframework/test/context/web/AnnotationConfigWebContextLoaderTests.java

@ -1,5 +1,5 @@ @@ -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.
@ -39,7 +39,7 @@ class AnnotationConfigWebContextLoaderTests { @@ -39,7 +39,7 @@ class AnnotationConfigWebContextLoaderTests {
new String[] { "config.xml" }, EMPTY_CLASS_ARRAY, null, EMPTY_STRING_ARRAY, EMPTY_STRING_ARRAY,
EMPTY_STRING_ARRAY, "resource/path", loader, null, null);
assertThatIllegalStateException()
.isThrownBy(() -> loader.loadContext(mergedConfig))
.isThrownBy(() -> loader.loadContext(mergedConfig, true))
.withMessageContaining("does not support resource locations");
}

4
spring-test/src/test/java/org/springframework/test/context/web/GenericXmlWebContextLoaderTests.java

@ -1,5 +1,5 @@ @@ -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.
@ -38,7 +38,7 @@ class GenericXmlWebContextLoaderTests { @@ -38,7 +38,7 @@ class GenericXmlWebContextLoaderTests {
new Class<?>[] { getClass() }, null, EMPTY_STRING_ARRAY, EMPTY_STRING_ARRAY, EMPTY_STRING_ARRAY,
"resource/path", loader, null, null);
assertThatIllegalStateException()
.isThrownBy(() -> loader.loadContext(mergedConfig))
.isThrownBy(() -> loader.loadContext(mergedConfig, true))
.withMessageContaining("does not support annotated classes");
}

Loading…
Cancel
Save