Support ApplicationContextInitializers in the TCF
Starting with Spring 3.1 applications can specify contextInitializerClasses via context-param and init-param in web.xml; however, there is currently no way to have such initializers invoked in integration testing scenarios without writing a custom SmartContextLoader. For comprehensive integration testing it should therefore be possible to re-use ApplicationContextInitializers in the Spring TestContext Framework as well. This commit makes this possible at the @ContextConfiguration level by allowing an array of ACI types to be specified, and the out-of-the-box SmartContextLoader implementations invoke the declared initializers at the appropriate time. - Added initializers and inheritInitializers attributes to @ContextConfiguration. - Introduced support for ApplicationContextInitializers in ContextConfigurationAttributes, MergedContextConfiguration, and ContextLoaderUtils. - MergedContextConfiguration stores context initializer classes as a Set and incorporates them into the implementations of hashCode() and equals() for proper context caching. - ApplicationContextInitializers are invoked in the new prepareContext(GenericApplicationContext, MergedContextConfiguration) method in AbstractGenericContextLoader, and ordering declared via the Ordered interface and @Order annotation is honored. - Updated DelegatingSmartContextLoader to support initializers. Specifically, a test class may optionally declare neither XML configuration files nor annotated classes and instead declare only application context initializers. In such cases, an attempt will still be made to detect defaults, but their absence will not result an an exception. - Documented support for application context initializers in Javadoc and in the testing chapter of the reference manual. Issue: SPR-9011
This commit is contained in:
parent
9c8c967caa
commit
1f93777bbd
|
@ -1,13 +1,14 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<beansProjectDescription>
|
<beansProjectDescription>
|
||||||
<version>1</version>
|
<version>1</version>
|
||||||
<pluginVersion><![CDATA[2.6.0.201104111100-PATCH]]></pluginVersion>
|
<pluginVersion><![CDATA[3.0.0.201208090952-RELEASE]]></pluginVersion>
|
||||||
<configSuffixes>
|
<configSuffixes>
|
||||||
<configSuffix><![CDATA[xml]]></configSuffix>
|
<configSuffix><![CDATA[xml]]></configSuffix>
|
||||||
</configSuffixes>
|
</configSuffixes>
|
||||||
<enableImports><![CDATA[false]]></enableImports>
|
<enableImports><![CDATA[false]]></enableImports>
|
||||||
<configs>
|
<configs>
|
||||||
<config>src/test/java/org/springframework/test/context/junit4/profile/xml/DefaultProfileXmlConfigTests-context.xml</config>
|
<config>src/test/java/org/springframework/test/context/junit4/profile/xml/DefaultProfileXmlConfigTests-context.xml</config>
|
||||||
|
<config>src/test/java/org/springframework/test/context/junit4/aci/xml/MultipleInitializersXmlConfigTests-context.xml</config>
|
||||||
</configs>
|
</configs>
|
||||||
<configSets>
|
<configSets>
|
||||||
</configSets>
|
</configSets>
|
||||||
|
|
|
@ -23,19 +23,19 @@ import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.RetentionPolicy;
|
import java.lang.annotation.RetentionPolicy;
|
||||||
import java.lang.annotation.Target;
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.ApplicationContextInitializer;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.ConfigurableApplicationContext;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@code ContextConfiguration} defines class-level metadata that is
|
* {@code @ContextConfiguration} defines class-level metadata that is
|
||||||
* used to determine how to load and configure an
|
* used to determine how to load and configure an
|
||||||
* {@link org.springframework.context.ApplicationContext ApplicationContext}
|
* {@link org.springframework.context.ApplicationContext ApplicationContext}
|
||||||
* for test classes.
|
* for integration tests.
|
||||||
*
|
*
|
||||||
* <h3>Supported Resource Types</h3>
|
* <h3>Supported Resource Types</h3>
|
||||||
*
|
*
|
||||||
* <p>Prior to Spring 3.1, only path-based resource locations were supported.
|
* <p>Prior to Spring 3.1, only path-based resource locations were supported.
|
||||||
* As of Spring 3.1, {@link #loader context loaders} may choose to support
|
* As of Spring 3.1, {@linkplain #loader context loaders} may choose to support
|
||||||
* either path-based or class-based resources (but not both). Consequently
|
* either path-based or class-based resources (but not both). Consequently
|
||||||
* {@code @ContextConfiguration} can be used to declare either path-based
|
* {@code @ContextConfiguration} can be used to declare either path-based
|
||||||
* resource locations (via the {@link #locations} or {@link #value}
|
* resource locations (via the {@link #locations} or {@link #value}
|
||||||
|
@ -47,16 +47,20 @@ import org.springframework.context.annotation.Configuration;
|
||||||
* <p>The term <em>annotated class</em> can refer to any of the following.
|
* <p>The term <em>annotated class</em> can refer to any of the following.
|
||||||
*
|
*
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>A class annotated with {@link Configuration @Configuration}</li>
|
* <li>A class annotated with
|
||||||
|
* {@link org.springframework.context.annotation.Configuration @Configuration}</li>
|
||||||
* <li>A component (i.e., a class annotated with
|
* <li>A component (i.e., a class annotated with
|
||||||
* {@link org.springframework.stereotype.Component @Component},
|
* {@link org.springframework.stereotype.Component @Component},
|
||||||
* {@link org.springframework.stereotype.Service @Service},
|
* {@link org.springframework.stereotype.Service @Service},
|
||||||
* {@link org.springframework.stereotype.Repository @Repository}, etc.)</li>
|
* {@link org.springframework.stereotype.Repository @Repository}, etc.)</li>
|
||||||
* <li>A JSR-330 compliant class that is annotated with {@code javax.inject} annotations</li>
|
* <li>A JSR-330 compliant class that is annotated with {@code javax.inject} annotations</li>
|
||||||
* <li>Any other class that contains {@link Bean @Bean}-methods</li>
|
* <li>Any other class that contains
|
||||||
|
* {@link org.springframework.context.annotation.Bean @Bean}-methods</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
*
|
*
|
||||||
* Consult the JavaDoc for {@link Configuration @Configuration} and {@link Bean @Bean}
|
* Consult the Javadoc for
|
||||||
|
* {@link org.springframework.context.annotation.Configuration @Configuration} and
|
||||||
|
* {@link org.springframework.context.annotation.Bean @Bean}
|
||||||
* for further information regarding the configuration and semantics of
|
* for further information regarding the configuration and semantics of
|
||||||
* <em>annotated classes</em>.
|
* <em>annotated classes</em>.
|
||||||
*
|
*
|
||||||
|
@ -66,8 +70,8 @@ import org.springframework.context.annotation.Configuration;
|
||||||
* @see SmartContextLoader
|
* @see SmartContextLoader
|
||||||
* @see ContextConfigurationAttributes
|
* @see ContextConfigurationAttributes
|
||||||
* @see MergedContextConfiguration
|
* @see MergedContextConfiguration
|
||||||
* @see org.springframework.context.ApplicationContext
|
|
||||||
* @see ActiveProfiles
|
* @see ActiveProfiles
|
||||||
|
* @see org.springframework.context.ApplicationContext
|
||||||
*/
|
*/
|
||||||
@Documented
|
@Documented
|
||||||
@Inherited
|
@Inherited
|
||||||
|
@ -82,6 +86,7 @@ public @interface ContextConfiguration {
|
||||||
* with {@link #locations} or {@link #classes}, but it may be used
|
* with {@link #locations} or {@link #classes}, but it may be used
|
||||||
* instead of {@link #locations}.
|
* instead of {@link #locations}.
|
||||||
* @since 3.0
|
* @since 3.0
|
||||||
|
* @see #inheritLocations
|
||||||
*/
|
*/
|
||||||
String[] value() default {};
|
String[] value() default {};
|
||||||
|
|
||||||
|
@ -111,6 +116,7 @@ public @interface ContextConfiguration {
|
||||||
* {@link #value} or {@link #classes}, but it may be used instead of
|
* {@link #value} or {@link #classes}, but it may be used instead of
|
||||||
* {@link #value}.
|
* {@link #value}.
|
||||||
* @since 2.5
|
* @since 2.5
|
||||||
|
* @see #inheritLocations
|
||||||
*/
|
*/
|
||||||
String[] locations() default {};
|
String[] locations() default {};
|
||||||
|
|
||||||
|
@ -131,9 +137,31 @@ public @interface ContextConfiguration {
|
||||||
* @since 3.1
|
* @since 3.1
|
||||||
* @see org.springframework.context.annotation.Configuration
|
* @see org.springframework.context.annotation.Configuration
|
||||||
* @see org.springframework.test.context.support.AnnotationConfigContextLoader
|
* @see org.springframework.test.context.support.AnnotationConfigContextLoader
|
||||||
|
* @see #inheritLocations
|
||||||
*/
|
*/
|
||||||
Class<?>[] classes() default {};
|
Class<?>[] classes() default {};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The application context <em>initializer classes</em> to use for initializing
|
||||||
|
* a {@link ConfigurableApplicationContext}.
|
||||||
|
*
|
||||||
|
* <p>The concrete {@code ConfigurableApplicationContext} type supported by each
|
||||||
|
* declared initializer must be compatible with the type of {@code ApplicationContext}
|
||||||
|
* created by the {@link SmartContextLoader} in use.
|
||||||
|
*
|
||||||
|
* <p>{@code SmartContextLoader} implementations typically detect whether
|
||||||
|
* Spring's {@link org.springframework.core.Ordered Ordered} interface has been
|
||||||
|
* implemented or if the @{@link org.springframework.core.annotation.Order Order}
|
||||||
|
* annotation is present and sort instances accordingly prior to invoking them.
|
||||||
|
*
|
||||||
|
* @since 3.2
|
||||||
|
* @see org.springframework.context.ApplicationContextInitializer
|
||||||
|
* @see org.springframework.context.ConfigurableApplicationContext
|
||||||
|
* @see #inheritInitializers
|
||||||
|
* @see #loader
|
||||||
|
*/
|
||||||
|
Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>[] initializers() default {};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Whether or not {@link #locations resource locations} or <em>annotated
|
* Whether or not {@link #locations resource locations} or <em>annotated
|
||||||
* classes</em> from test superclasses should be <em>inherited</em>.
|
* classes</em> from test superclasses should be <em>inherited</em>.
|
||||||
|
@ -194,7 +222,45 @@ public @interface ContextConfiguration {
|
||||||
boolean inheritLocations() default true;
|
boolean inheritLocations() default true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The type of {@link ContextLoader} (or {@link SmartContextLoader}) to use
|
* Whether or not {@linkplain #initializers context initializers} from test
|
||||||
|
* superclasses should be <em>inherited</em>.
|
||||||
|
*
|
||||||
|
* <p>The default value is <code>true</code>. This means that an annotated
|
||||||
|
* class will <em>inherit</em> the application context initializers defined
|
||||||
|
* by test superclasses. Specifically, the initializers for a given test
|
||||||
|
* class will be added to the set of initializers defined by test
|
||||||
|
* superclasses. Thus, subclasses have the option of <em>extending</em> the
|
||||||
|
* set of initializers.
|
||||||
|
*
|
||||||
|
* <p>If <code>inheritInitializers</code> is set to <code>false</code>, the
|
||||||
|
* initializers for the annotated class will <em>shadow</em> and effectively
|
||||||
|
* replace any initializers defined by superclasses.
|
||||||
|
*
|
||||||
|
* <p>In the following example, the
|
||||||
|
* {@link org.springframework.context.ApplicationContext ApplicationContext}
|
||||||
|
* for {@code ExtendedTest} will be initialized using
|
||||||
|
* {@code BaseInitializer} <strong>and</strong> {@code ExtendedInitializer}.
|
||||||
|
* Note, however, that the order in which the initializers are invoked
|
||||||
|
* depends on whether they implement {@link org.springframework.core.Ordered
|
||||||
|
* Ordered} or are annotated with {@link org.springframework.core.annotation.Order
|
||||||
|
* @Order}.
|
||||||
|
* <pre class="code">
|
||||||
|
* @ContextConfiguration(initializers = BaseInitializer.class)
|
||||||
|
* public class BaseTest {
|
||||||
|
* // ...
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* @ContextConfiguration(initializers = ExtendedInitializer.class)
|
||||||
|
* public class ExtendedTest extends BaseTest {
|
||||||
|
* // ...
|
||||||
|
* }
|
||||||
|
* </pre>
|
||||||
|
* @since 3.2
|
||||||
|
*/
|
||||||
|
boolean inheritInitializers() default true;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The type of {@link SmartContextLoader} (or {@link ContextLoader}) to use
|
||||||
* for loading an {@link org.springframework.context.ApplicationContext
|
* for loading an {@link org.springframework.context.ApplicationContext
|
||||||
* ApplicationContext}.
|
* ApplicationContext}.
|
||||||
*
|
*
|
||||||
|
|
|
@ -18,12 +18,15 @@ package org.springframework.test.context;
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
|
import org.springframework.context.ApplicationContextInitializer;
|
||||||
|
import org.springframework.context.ConfigurableApplicationContext;
|
||||||
import org.springframework.core.style.ToStringCreator;
|
import org.springframework.core.style.ToStringCreator;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.util.ObjectUtils;
|
import org.springframework.util.ObjectUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <code>ContextConfigurationAttributes</code> encapsulates the context
|
* {@code ContextConfigurationAttributes} encapsulates the context
|
||||||
* configuration attributes declared on a test class via
|
* configuration attributes declared on a test class via
|
||||||
* {@link ContextConfiguration @ContextConfiguration}.
|
* {@link ContextConfiguration @ContextConfiguration}.
|
||||||
*
|
*
|
||||||
|
@ -47,6 +50,10 @@ public class ContextConfigurationAttributes {
|
||||||
|
|
||||||
private final Class<? extends ContextLoader> contextLoaderClass;
|
private final Class<? extends ContextLoader> contextLoaderClass;
|
||||||
|
|
||||||
|
private final Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>[] initializers;
|
||||||
|
|
||||||
|
private final boolean inheritInitializers;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolve resource locations from the {@link ContextConfiguration#locations() locations}
|
* Resolve resource locations from the {@link ContextConfiguration#locations() locations}
|
||||||
|
@ -68,8 +75,7 @@ public class ContextConfigurationAttributes {
|
||||||
ObjectUtils.nullSafeToString(valueLocations), ObjectUtils.nullSafeToString(locations));
|
ObjectUtils.nullSafeToString(valueLocations), ObjectUtils.nullSafeToString(locations));
|
||||||
logger.error(msg);
|
logger.error(msg);
|
||||||
throw new IllegalStateException(msg);
|
throw new IllegalStateException(msg);
|
||||||
}
|
} else if (!ObjectUtils.isEmpty(valueLocations)) {
|
||||||
else if (!ObjectUtils.isEmpty(valueLocations)) {
|
|
||||||
locations = valueLocations;
|
locations = valueLocations;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,31 +85,59 @@ public class ContextConfigurationAttributes {
|
||||||
/**
|
/**
|
||||||
* Construct a new {@link ContextConfigurationAttributes} instance for the
|
* Construct a new {@link ContextConfigurationAttributes} instance for the
|
||||||
* supplied {@link ContextConfiguration @ContextConfiguration} annotation and
|
* supplied {@link ContextConfiguration @ContextConfiguration} annotation and
|
||||||
* the {@link Class test class} that declared it.
|
* the {@linkplain Class test class} that declared it.
|
||||||
* @param declaringClass the test class that declared {@code @ContextConfiguration}
|
* @param declaringClass the test class that declared {@code @ContextConfiguration}
|
||||||
* @param contextConfiguration the annotation from which to retrieve the attributes
|
* @param contextConfiguration the annotation from which to retrieve the attributes
|
||||||
*/
|
*/
|
||||||
public ContextConfigurationAttributes(Class<?> declaringClass, ContextConfiguration contextConfiguration) {
|
public ContextConfigurationAttributes(Class<?> declaringClass, ContextConfiguration contextConfiguration) {
|
||||||
this(declaringClass, resolveLocations(declaringClass, contextConfiguration), contextConfiguration.classes(),
|
this(declaringClass, resolveLocations(declaringClass, contextConfiguration), contextConfiguration.classes(),
|
||||||
contextConfiguration.inheritLocations(), contextConfiguration.loader());
|
contextConfiguration.inheritLocations(), contextConfiguration.initializers(),
|
||||||
|
contextConfiguration.inheritInitializers(), contextConfiguration.loader());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a new {@link ContextConfigurationAttributes} instance for the
|
* Construct a new {@link ContextConfigurationAttributes} instance for the
|
||||||
* {@link Class test class} that declared the
|
* {@linkplain Class test class} that declared the
|
||||||
* {@link ContextConfiguration @ContextConfiguration} annotation and its
|
* {@link ContextConfiguration @ContextConfiguration} annotation and its
|
||||||
* corresponding attributes.
|
* corresponding attributes.
|
||||||
*
|
*
|
||||||
* @param declaringClass the test class that declared {@code @ContextConfiguration}
|
* @param declaringClass the test class that declared {@code @ContextConfiguration}
|
||||||
* @param locations the resource locations declared via {@code @ContextConfiguration}
|
* @param locations the resource locations declared via {@code @ContextConfiguration}
|
||||||
* @param classes the annotated classes declared via {@code @ContextConfiguration}
|
* @param classes the annotated classes declared via {@code @ContextConfiguration}
|
||||||
* @param inheritLocations the <code>inheritLocations</code> flag declared via {@code @ContextConfiguration}
|
* @param inheritLocations the {@code inheritLocations} flag declared via {@code @ContextConfiguration}
|
||||||
* @param contextLoaderClass the {@code ContextLoader} class declared via {@code @ContextConfiguration}
|
* @param contextLoaderClass the {@code ContextLoader} class declared via {@code @ContextConfiguration}
|
||||||
* @throws IllegalArgumentException if the {@code declaringClass} or {@code contextLoaderClass} is
|
* @throws IllegalArgumentException if the {@code declaringClass} or {@code contextLoaderClass} is
|
||||||
* <code>null</code>, or if the {@code locations} and {@code classes} are both non-empty
|
* {@code null}, or if the {@code locations} and {@code classes} are both non-empty
|
||||||
|
* @deprecated as of Spring 3.2, use
|
||||||
|
* {@link #ContextConfigurationAttributes(Class, String[], Class[], boolean, Class[], boolean, Class)}
|
||||||
|
* instead
|
||||||
*/
|
*/
|
||||||
|
@Deprecated
|
||||||
public ContextConfigurationAttributes(Class<?> declaringClass, String[] locations, Class<?>[] classes,
|
public ContextConfigurationAttributes(Class<?> declaringClass, String[] locations, Class<?>[] classes,
|
||||||
boolean inheritLocations, Class<? extends ContextLoader> contextLoaderClass) {
|
boolean inheritLocations, Class<? extends ContextLoader> contextLoaderClass) {
|
||||||
|
this(declaringClass, locations, classes, inheritLocations, null, true, contextLoaderClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Construct a new {@link ContextConfigurationAttributes} instance for the
|
||||||
|
* {@linkplain Class test class} that declared the
|
||||||
|
* {@link ContextConfiguration @ContextConfiguration} annotation and its
|
||||||
|
* corresponding attributes.
|
||||||
|
*
|
||||||
|
* @param declaringClass the test class that declared {@code @ContextConfiguration}
|
||||||
|
* @param locations the resource locations declared via {@code @ContextConfiguration}
|
||||||
|
* @param classes the annotated classes declared via {@code @ContextConfiguration}
|
||||||
|
* @param inheritLocations the {@code inheritLocations} flag declared via {@code @ContextConfiguration}
|
||||||
|
* @param initializers the context initializers declared via {@code @ContextConfiguration}
|
||||||
|
* @param inheritInitializers the {@code inheritInitializers} flag declared via {@code @ContextConfiguration}
|
||||||
|
* @param contextLoaderClass the {@code ContextLoader} class declared via {@code @ContextConfiguration}
|
||||||
|
* @throws IllegalArgumentException if the {@code declaringClass} or {@code contextLoaderClass} is
|
||||||
|
* {@code null}, or if the {@code locations} and {@code classes} are both non-empty
|
||||||
|
*/
|
||||||
|
public ContextConfigurationAttributes(Class<?> declaringClass, String[] locations, Class<?>[] classes,
|
||||||
|
boolean inheritLocations,
|
||||||
|
Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>[] initializers,
|
||||||
|
boolean inheritInitializers, Class<? extends ContextLoader> contextLoaderClass) {
|
||||||
|
|
||||||
Assert.notNull(declaringClass, "declaringClass must not be null");
|
Assert.notNull(declaringClass, "declaringClass must not be null");
|
||||||
Assert.notNull(contextLoaderClass, "contextLoaderClass must not be null");
|
Assert.notNull(contextLoaderClass, "contextLoaderClass must not be null");
|
||||||
|
@ -122,14 +156,16 @@ public class ContextConfigurationAttributes {
|
||||||
this.locations = locations;
|
this.locations = locations;
|
||||||
this.classes = classes;
|
this.classes = classes;
|
||||||
this.inheritLocations = inheritLocations;
|
this.inheritLocations = inheritLocations;
|
||||||
|
this.initializers = initializers;
|
||||||
|
this.inheritInitializers = inheritInitializers;
|
||||||
this.contextLoaderClass = contextLoaderClass;
|
this.contextLoaderClass = contextLoaderClass;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the {@link Class class} that declared the
|
* Get the {@linkplain Class class} that declared the
|
||||||
* {@link ContextConfiguration @ContextConfiguration} annotation.
|
* {@link ContextConfiguration @ContextConfiguration} annotation.
|
||||||
*
|
*
|
||||||
* @return the declaring class; never <code>null</code>
|
* @return the declaring class; never {@code null}
|
||||||
*/
|
*/
|
||||||
public Class<?> getDeclaringClass() {
|
public Class<?> getDeclaringClass() {
|
||||||
return declaringClass;
|
return declaringClass;
|
||||||
|
@ -143,7 +179,7 @@ public class ContextConfigurationAttributes {
|
||||||
* represent a <em>processed</em> value that does not match the original value
|
* represent a <em>processed</em> value that does not match the original value
|
||||||
* declared via {@link ContextConfiguration @ContextConfiguration}.
|
* declared via {@link ContextConfiguration @ContextConfiguration}.
|
||||||
*
|
*
|
||||||
* @return the resource locations; potentially <code>null</code> or <em>empty</em>
|
* @return the resource locations; potentially {@code null} or <em>empty</em>
|
||||||
* @see ContextConfiguration#value
|
* @see ContextConfiguration#value
|
||||||
* @see ContextConfiguration#locations
|
* @see ContextConfiguration#locations
|
||||||
* @see #setLocations(String[])
|
* @see #setLocations(String[])
|
||||||
|
@ -170,7 +206,7 @@ public class ContextConfigurationAttributes {
|
||||||
* represent a <em>processed</em> value that does not match the original value
|
* represent a <em>processed</em> value that does not match the original value
|
||||||
* declared via {@link ContextConfiguration @ContextConfiguration}.
|
* declared via {@link ContextConfiguration @ContextConfiguration}.
|
||||||
*
|
*
|
||||||
* @return the annotated classes; potentially <code>null</code> or <em>empty</em>
|
* @return the annotated classes; potentially {@code null} or <em>empty</em>
|
||||||
* @see ContextConfiguration#classes
|
* @see ContextConfiguration#classes
|
||||||
* @see #setClasses(Class[])
|
* @see #setClasses(Class[])
|
||||||
*/
|
*/
|
||||||
|
@ -192,7 +228,7 @@ public class ContextConfigurationAttributes {
|
||||||
* Determine if this {@code ContextConfigurationAttributes} instance has
|
* Determine if this {@code ContextConfigurationAttributes} instance has
|
||||||
* path-based resource locations.
|
* path-based resource locations.
|
||||||
*
|
*
|
||||||
* @return <code>true</code> if the {@link #getLocations() locations} array is not empty
|
* @return {@code true} if the {@link #getLocations() locations} array is not empty
|
||||||
* @see #hasResources()
|
* @see #hasResources()
|
||||||
* @see #hasClasses()
|
* @see #hasClasses()
|
||||||
*/
|
*/
|
||||||
|
@ -204,7 +240,7 @@ public class ContextConfigurationAttributes {
|
||||||
* Determine if this {@code ContextConfigurationAttributes} instance has
|
* Determine if this {@code ContextConfigurationAttributes} instance has
|
||||||
* class-based resources.
|
* class-based resources.
|
||||||
*
|
*
|
||||||
* @return <code>true</code> if the {@link #getClasses() classes} array is not empty
|
* @return {@code true} if the {@link #getClasses() classes} array is not empty
|
||||||
* @see #hasResources()
|
* @see #hasResources()
|
||||||
* @see #hasLocations()
|
* @see #hasLocations()
|
||||||
*/
|
*/
|
||||||
|
@ -216,7 +252,7 @@ public class ContextConfigurationAttributes {
|
||||||
* Determine if this {@code ContextConfigurationAttributes} instance has
|
* Determine if this {@code ContextConfigurationAttributes} instance has
|
||||||
* either path-based resource locations or class-based resources.
|
* either path-based resource locations or class-based resources.
|
||||||
*
|
*
|
||||||
* @return <code>true</code> if either the {@link #getLocations() locations}
|
* @return {@code true} if either the {@link #getLocations() locations}
|
||||||
* or the {@link #getClasses() classes} array is not empty
|
* or the {@link #getClasses() classes} array is not empty
|
||||||
* @see #hasLocations()
|
* @see #hasLocations()
|
||||||
* @see #hasClasses()
|
* @see #hasClasses()
|
||||||
|
@ -226,10 +262,10 @@ public class ContextConfigurationAttributes {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the <code>inheritLocations</code> flag that was declared via
|
* Get the {@code inheritLocations} flag that was declared via
|
||||||
* {@link ContextConfiguration @ContextConfiguration}.
|
* {@link ContextConfiguration @ContextConfiguration}.
|
||||||
*
|
*
|
||||||
* @return the <code>inheritLocations</code> flag
|
* @return the {@code inheritLocations} flag
|
||||||
* @see ContextConfiguration#inheritLocations
|
* @see ContextConfiguration#inheritLocations
|
||||||
*/
|
*/
|
||||||
public boolean isInheritLocations() {
|
public boolean isInheritLocations() {
|
||||||
|
@ -237,10 +273,32 @@ public class ContextConfigurationAttributes {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the <code>ContextLoader</code> class that was declared via
|
* Get the {@code ApplicationContextInitializer} classes that were declared via
|
||||||
* {@link ContextConfiguration @ContextConfiguration}.
|
* {@link ContextConfiguration @ContextConfiguration}.
|
||||||
*
|
*
|
||||||
* @return the <code>ContextLoader</code> class
|
* @return the {@code ApplicationContextInitializer} classes
|
||||||
|
* @since 3.2
|
||||||
|
*/
|
||||||
|
public Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>[] getInitializers() {
|
||||||
|
return initializers;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the {@code inheritInitializers} flag that was declared via
|
||||||
|
* {@link ContextConfiguration @ContextConfiguration}.
|
||||||
|
*
|
||||||
|
* @return the {@code inheritInitializers} flag
|
||||||
|
* @since 3.2
|
||||||
|
*/
|
||||||
|
public boolean isInheritInitializers() {
|
||||||
|
return inheritInitializers;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the {@code ContextLoader} class that was declared via
|
||||||
|
* {@link ContextConfiguration @ContextConfiguration}.
|
||||||
|
*
|
||||||
|
* @return the {@code ContextLoader} class
|
||||||
* @see ContextConfiguration#loader
|
* @see ContextConfiguration#loader
|
||||||
*/
|
*/
|
||||||
public Class<? extends ContextLoader> getContextLoaderClass() {
|
public Class<? extends ContextLoader> getContextLoaderClass() {
|
||||||
|
@ -258,6 +316,8 @@ public class ContextConfigurationAttributes {
|
||||||
.append("locations", ObjectUtils.nullSafeToString(locations))//
|
.append("locations", ObjectUtils.nullSafeToString(locations))//
|
||||||
.append("classes", ObjectUtils.nullSafeToString(classes))//
|
.append("classes", ObjectUtils.nullSafeToString(classes))//
|
||||||
.append("inheritLocations", inheritLocations)//
|
.append("inheritLocations", inheritLocations)//
|
||||||
|
.append("initializers", ObjectUtils.nullSafeToString(initializers))//
|
||||||
|
.append("inheritInitializers", inheritInitializers)//
|
||||||
.append("contextLoaderClass", contextLoaderClass.getName())//
|
.append("contextLoaderClass", contextLoaderClass.getName())//
|
||||||
.toString();
|
.toString();
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,8 +23,8 @@ import org.springframework.context.ApplicationContext;
|
||||||
* for an integration test managed by the Spring TestContext Framework.
|
* for an integration test managed by the Spring TestContext Framework.
|
||||||
*
|
*
|
||||||
* <p><b>Note</b>: as of Spring 3.1, implement {@link SmartContextLoader} instead
|
* <p><b>Note</b>: as of Spring 3.1, implement {@link SmartContextLoader} instead
|
||||||
* of this interface in order to provide support for annotated classes and active
|
* of this interface in order to provide support for annotated classes, active
|
||||||
* bean definition profiles.
|
* bean definition profiles, and application context initializers.
|
||||||
*
|
*
|
||||||
* <p>Clients of a ContextLoader should call
|
* <p>Clients of a ContextLoader should call
|
||||||
* {@link #processLocations(Class,String...) processLocations()} prior to
|
* {@link #processLocations(Class,String...) processLocations()} prior to
|
||||||
|
|
|
@ -21,12 +21,15 @@ import static org.springframework.core.annotation.AnnotationUtils.findAnnotation
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
import org.springframework.context.ApplicationContextInitializer;
|
||||||
|
import org.springframework.context.ConfigurableApplicationContext;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.util.ClassUtils;
|
import org.springframework.util.ClassUtils;
|
||||||
import org.springframework.util.ObjectUtils;
|
import org.springframework.util.ObjectUtils;
|
||||||
|
@ -156,8 +159,7 @@ abstract class ContextLoaderUtils {
|
||||||
}
|
}
|
||||||
return (Class<? extends ContextLoader>) ContextLoaderUtils.class.getClassLoader().loadClass(
|
return (Class<? extends ContextLoader>) ContextLoaderUtils.class.getClassLoader().loadClass(
|
||||||
defaultContextLoaderClassName);
|
defaultContextLoaderClassName);
|
||||||
}
|
} catch (ClassNotFoundException ex) {
|
||||||
catch (ClassNotFoundException ex) {
|
|
||||||
throw new IllegalStateException("Could not load default ContextLoader class ["
|
throw new IllegalStateException("Could not load default ContextLoader class ["
|
||||||
+ defaultContextLoaderClassName + "]. Specify @ContextConfiguration's 'loader' "
|
+ defaultContextLoaderClassName + "]. Specify @ContextConfiguration's 'loader' "
|
||||||
+ "attribute or make the default loader class available.");
|
+ "attribute or make the default loader class available.");
|
||||||
|
@ -169,17 +171,15 @@ abstract class ContextLoaderUtils {
|
||||||
* attributes} for the supplied {@link Class class} and its superclasses.
|
* attributes} for the supplied {@link Class class} and its superclasses.
|
||||||
*
|
*
|
||||||
* <p>Note that the {@link ContextConfiguration#inheritLocations
|
* <p>Note that the {@link ContextConfiguration#inheritLocations
|
||||||
* inheritLocations} flag of {@link ContextConfiguration
|
* inheritLocations} and {@link ContextConfiguration#inheritInitializers()
|
||||||
* @ContextConfiguration} will be taken into consideration.
|
* inheritInitializers} flags of {@link ContextConfiguration
|
||||||
* Specifically, if the <code>inheritLocations</code> flag is set to
|
* @ContextConfiguration} will <strong>not</strong> be taken into
|
||||||
* <code>true</code>, configuration attributes defined in the test
|
* consideration. If these flags need to be honored, that must be handled
|
||||||
* class will be appended to the configuration attributes defined in
|
* manually when traversing the list returned by this method.
|
||||||
* superclasses.
|
|
||||||
*
|
*
|
||||||
* @param clazz the class for which to resolve the configuration attributes (must
|
* @param clazz the class for which to resolve the configuration attributes (must
|
||||||
* not be <code>null</code>)
|
* not be <code>null</code>)
|
||||||
* @return the list of configuration attributes for the specified class,
|
* @return the list of configuration attributes for the specified class
|
||||||
* including configuration attributes from superclasses if appropriate
|
|
||||||
* (never <code>null</code>)
|
* (never <code>null</code>)
|
||||||
* @throws IllegalArgumentException if the supplied class is <code>null</code> or
|
* @throws IllegalArgumentException if the supplied class is <code>null</code> or
|
||||||
* if {@code @ContextConfiguration} is not <em>present</em> on the supplied class
|
* if {@code @ContextConfiguration} is not <em>present</em> on the supplied class
|
||||||
|
@ -211,13 +211,69 @@ abstract class ContextLoaderUtils {
|
||||||
|
|
||||||
attributesList.add(0, attributes);
|
attributesList.add(0, attributes);
|
||||||
|
|
||||||
declaringClass = contextConfiguration.inheritLocations() ? findAnnotationDeclaringClass(annotationType,
|
declaringClass = findAnnotationDeclaringClass(annotationType, declaringClass.getSuperclass());
|
||||||
declaringClass.getSuperclass()) : null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return attributesList;
|
return attributesList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a copy of the supplied list of {@code ContextConfigurationAttributes}
|
||||||
|
* in reverse order.
|
||||||
|
*
|
||||||
|
* @since 3.2
|
||||||
|
*/
|
||||||
|
private static List<ContextConfigurationAttributes> reverseContextConfigurationAttributes(
|
||||||
|
List<ContextConfigurationAttributes> configAttributesList) {
|
||||||
|
List<ContextConfigurationAttributes> configAttributesListReversed = new ArrayList<ContextConfigurationAttributes>(
|
||||||
|
configAttributesList);
|
||||||
|
Collections.reverse(configAttributesListReversed);
|
||||||
|
return configAttributesListReversed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolve the list of merged {@code ApplicationContextInitializer} classes
|
||||||
|
* for the supplied list of {@code ContextConfigurationAttributes}.
|
||||||
|
*
|
||||||
|
* <p>Note that the {@link ContextConfiguration#inheritInitializers inheritInitializers}
|
||||||
|
* flag of {@link ContextConfiguration @ContextConfiguration} will be taken into
|
||||||
|
* consideration. Specifically, if the <code>inheritInitializers</code> flag is
|
||||||
|
* set to <code>true</code> for a given level in the class hierarchy represented by
|
||||||
|
* the provided configuration attributes, context initializer classes defined
|
||||||
|
* at the given level will be merged with those defined in higher levels
|
||||||
|
* of the class hierarchy.
|
||||||
|
*
|
||||||
|
* @param configAttributesList the list of configuration attributes to process
|
||||||
|
* (must not be <code>null</code>)
|
||||||
|
* @return the list of merged context initializer classes, including those
|
||||||
|
* from superclasses if appropriate (never <code>null</code>)
|
||||||
|
* @since 3.2
|
||||||
|
*/
|
||||||
|
static Set<Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>> resolveInitializerClasses(
|
||||||
|
List<ContextConfigurationAttributes> configAttributesList) {
|
||||||
|
Assert.notNull(configAttributesList, "configAttributesList must not be null");
|
||||||
|
|
||||||
|
final Set<Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>> initializerClasses = //
|
||||||
|
new HashSet<Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>>();
|
||||||
|
|
||||||
|
// Traverse config attributes in reverse order (i.e., as if we were traversing up
|
||||||
|
// the class hierarchy).
|
||||||
|
for (ContextConfigurationAttributes configAttributes : reverseContextConfigurationAttributes(configAttributesList)) {
|
||||||
|
if (logger.isTraceEnabled()) {
|
||||||
|
logger.trace(String.format("Processing context initializers for context configuration attributes %s",
|
||||||
|
configAttributes));
|
||||||
|
}
|
||||||
|
|
||||||
|
initializerClasses.addAll(Arrays.asList(configAttributes.getInitializers()));
|
||||||
|
|
||||||
|
if (!configAttributes.isInheritInitializers()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return initializerClasses;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolve <em>active bean definition profiles</em> for the supplied {@link Class}.
|
* Resolve <em>active bean definition profiles</em> for the supplied {@link Class}.
|
||||||
*
|
*
|
||||||
|
@ -266,8 +322,7 @@ abstract class ContextLoaderUtils {
|
||||||
ObjectUtils.nullSafeToString(valueProfiles), ObjectUtils.nullSafeToString(profiles));
|
ObjectUtils.nullSafeToString(valueProfiles), ObjectUtils.nullSafeToString(profiles));
|
||||||
logger.error(msg);
|
logger.error(msg);
|
||||||
throw new IllegalStateException(msg);
|
throw new IllegalStateException(msg);
|
||||||
}
|
} else if (!ObjectUtils.isEmpty(valueProfiles)) {
|
||||||
else if (!ObjectUtils.isEmpty(valueProfiles)) {
|
|
||||||
profiles = valueProfiles;
|
profiles = valueProfiles;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -309,31 +364,38 @@ abstract class ContextLoaderUtils {
|
||||||
final List<String> locationsList = new ArrayList<String>();
|
final List<String> locationsList = new ArrayList<String>();
|
||||||
final List<Class<?>> classesList = new ArrayList<Class<?>>();
|
final List<Class<?>> classesList = new ArrayList<Class<?>>();
|
||||||
|
|
||||||
for (ContextConfigurationAttributes configAttributes : configAttributesList) {
|
// Traverse config attributes in reverse order (i.e., as if we were traversing up
|
||||||
|
// the class hierarchy).
|
||||||
|
for (ContextConfigurationAttributes configAttributes : reverseContextConfigurationAttributes(configAttributesList)) {
|
||||||
if (logger.isTraceEnabled()) {
|
if (logger.isTraceEnabled()) {
|
||||||
logger.trace(String.format(
|
logger.trace(String.format("Processing locations and classes for context configuration attributes %s",
|
||||||
"Processing locations and classes for context configuration attributes [%s]", configAttributes));
|
configAttributes));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (contextLoader instanceof SmartContextLoader) {
|
if (contextLoader instanceof SmartContextLoader) {
|
||||||
SmartContextLoader smartContextLoader = (SmartContextLoader) contextLoader;
|
SmartContextLoader smartContextLoader = (SmartContextLoader) contextLoader;
|
||||||
smartContextLoader.processContextConfiguration(configAttributes);
|
smartContextLoader.processContextConfiguration(configAttributes);
|
||||||
locationsList.addAll(Arrays.asList(configAttributes.getLocations()));
|
locationsList.addAll(0, Arrays.asList(configAttributes.getLocations()));
|
||||||
classesList.addAll(Arrays.asList(configAttributes.getClasses()));
|
classesList.addAll(0, Arrays.asList(configAttributes.getClasses()));
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
String[] processedLocations = contextLoader.processLocations(configAttributes.getDeclaringClass(),
|
String[] processedLocations = contextLoader.processLocations(configAttributes.getDeclaringClass(),
|
||||||
configAttributes.getLocations());
|
configAttributes.getLocations());
|
||||||
locationsList.addAll(Arrays.asList(processedLocations));
|
locationsList.addAll(0, Arrays.asList(processedLocations));
|
||||||
// Legacy ContextLoaders don't know how to process classes
|
// Legacy ContextLoaders don't know how to process classes
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!configAttributes.isInheritLocations()) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String[] locations = StringUtils.toStringArray(locationsList);
|
String[] locations = StringUtils.toStringArray(locationsList);
|
||||||
Class<?>[] classes = ClassUtils.toClassArray(classesList);
|
Class<?>[] classes = ClassUtils.toClassArray(classesList);
|
||||||
|
Set<Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>> initializerClasses = resolveInitializerClasses(configAttributesList);
|
||||||
String[] activeProfiles = resolveActiveProfiles(testClass);
|
String[] activeProfiles = resolveActiveProfiles(testClass);
|
||||||
|
|
||||||
return new MergedContextConfiguration(testClass, locations, classes, activeProfiles, contextLoader);
|
return new MergedContextConfiguration(testClass, locations, classes, initializerClasses, activeProfiles,
|
||||||
|
contextLoader);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,9 +18,13 @@ package org.springframework.test.context;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Set;
|
||||||
import java.util.SortedSet;
|
import java.util.SortedSet;
|
||||||
import java.util.TreeSet;
|
import java.util.TreeSet;
|
||||||
|
|
||||||
|
import org.springframework.context.ApplicationContextInitializer;
|
||||||
|
import org.springframework.context.ConfigurableApplicationContext;
|
||||||
import org.springframework.core.style.ToStringCreator;
|
import org.springframework.core.style.ToStringCreator;
|
||||||
import org.springframework.util.ObjectUtils;
|
import org.springframework.util.ObjectUtils;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
@ -59,10 +63,13 @@ public class MergedContextConfiguration implements Serializable {
|
||||||
|
|
||||||
private static final String[] EMPTY_STRING_ARRAY = new String[0];
|
private static final String[] EMPTY_STRING_ARRAY = new String[0];
|
||||||
private static final Class<?>[] EMPTY_CLASS_ARRAY = new Class<?>[0];
|
private static final Class<?>[] EMPTY_CLASS_ARRAY = new Class<?>[0];
|
||||||
|
private static final Set<Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>> EMPTY_INITIALIZER_CLASSES = //
|
||||||
|
Collections.<Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>> emptySet();
|
||||||
|
|
||||||
private final Class<?> testClass;
|
private final Class<?> testClass;
|
||||||
private final String[] locations;
|
private final String[] locations;
|
||||||
private final Class<?>[] classes;
|
private final Class<?>[] classes;
|
||||||
|
private final Set<Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>> contextInitializerClasses;
|
||||||
private final String[] activeProfiles;
|
private final String[] activeProfiles;
|
||||||
private final ContextLoader contextLoader;
|
private final ContextLoader contextLoader;
|
||||||
|
|
||||||
|
@ -75,6 +82,12 @@ public class MergedContextConfiguration implements Serializable {
|
||||||
return classes == null ? EMPTY_CLASS_ARRAY : classes;
|
return classes == null ? EMPTY_CLASS_ARRAY : classes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Set<Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>> processContextInitializerClasses(
|
||||||
|
Set<Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>> contextInitializerClasses) {
|
||||||
|
return contextInitializerClasses == null ? EMPTY_INITIALIZER_CLASSES
|
||||||
|
: Collections.unmodifiableSet(contextInitializerClasses);
|
||||||
|
}
|
||||||
|
|
||||||
private static String[] processActiveProfiles(String[] activeProfiles) {
|
private static String[] processActiveProfiles(String[] activeProfiles) {
|
||||||
if (activeProfiles == null) {
|
if (activeProfiles == null) {
|
||||||
return EMPTY_STRING_ARRAY;
|
return EMPTY_STRING_ARRAY;
|
||||||
|
@ -111,46 +124,84 @@ public class MergedContextConfiguration implements Serializable {
|
||||||
* @param classes the merged annotated classes
|
* @param classes the merged annotated classes
|
||||||
* @param activeProfiles the merged active bean definition profiles
|
* @param activeProfiles the merged active bean definition profiles
|
||||||
* @param contextLoader the resolved <code>ContextLoader</code>
|
* @param contextLoader the resolved <code>ContextLoader</code>
|
||||||
|
* @see #MergedContextConfiguration(Class, String[], Class[], Set, String[], ContextLoader)
|
||||||
*/
|
*/
|
||||||
public MergedContextConfiguration(Class<?> testClass, String[] locations, Class<?>[] classes,
|
public MergedContextConfiguration(Class<?> testClass, String[] locations, Class<?>[] classes,
|
||||||
String[] activeProfiles, ContextLoader contextLoader) {
|
String[] activeProfiles, ContextLoader contextLoader) {
|
||||||
|
this(testClass, locations, classes, null, activeProfiles, contextLoader);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new {@code MergedContextConfiguration} instance for the
|
||||||
|
* supplied test class, resource locations, annotated classes, context
|
||||||
|
* initializers, active profiles, and {@code ContextLoader}.
|
||||||
|
*
|
||||||
|
* <p>If a <code>null</code> value is supplied for <code>locations</code>,
|
||||||
|
* <code>classes</code>, or <code>activeProfiles</code> an empty array will
|
||||||
|
* be stored instead. If a <code>null</code> value is supplied for the
|
||||||
|
* <code>contextInitializerClasses</code> an empty set will be stored instead.
|
||||||
|
* Furthermore, active profiles will be sorted, and duplicate profiles will
|
||||||
|
* be removed.
|
||||||
|
*
|
||||||
|
* @param testClass the test class for which the configuration was merged
|
||||||
|
* @param locations the merged resource locations
|
||||||
|
* @param classes the merged annotated classes
|
||||||
|
* @param contextInitializerClasses the merged context initializer classes
|
||||||
|
* @param activeProfiles the merged active bean definition profiles
|
||||||
|
* @param contextLoader the resolved <code>ContextLoader</code>
|
||||||
|
*/
|
||||||
|
public MergedContextConfiguration(
|
||||||
|
Class<?> testClass,
|
||||||
|
String[] locations,
|
||||||
|
Class<?>[] classes,
|
||||||
|
Set<Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>> contextInitializerClasses,
|
||||||
|
String[] activeProfiles, ContextLoader contextLoader) {
|
||||||
this.testClass = testClass;
|
this.testClass = testClass;
|
||||||
this.locations = processLocations(locations);
|
this.locations = processLocations(locations);
|
||||||
this.classes = processClasses(classes);
|
this.classes = processClasses(classes);
|
||||||
|
this.contextInitializerClasses = processContextInitializerClasses(contextInitializerClasses);
|
||||||
this.activeProfiles = processActiveProfiles(activeProfiles);
|
this.activeProfiles = processActiveProfiles(activeProfiles);
|
||||||
this.contextLoader = contextLoader;
|
this.contextLoader = contextLoader;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the {@link Class test class} associated with this {@code MergedContextConfiguration}.
|
* Get the {@linkplain Class test class} associated with this {@code MergedContextConfiguration}.
|
||||||
*/
|
*/
|
||||||
public Class<?> getTestClass() {
|
public Class<?> getTestClass() {
|
||||||
return testClass;
|
return testClass;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the merged resource locations for the {@link #getTestClass() test class}.
|
* Get the merged resource locations for the {@linkplain #getTestClass() test class}.
|
||||||
*/
|
*/
|
||||||
public String[] getLocations() {
|
public String[] getLocations() {
|
||||||
return locations;
|
return locations;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the merged annotated classes for the {@link #getTestClass() test class}.
|
* Get the merged annotated classes for the {@linkplain #getTestClass() test class}.
|
||||||
*/
|
*/
|
||||||
public Class<?>[] getClasses() {
|
public Class<?>[] getClasses() {
|
||||||
return classes;
|
return classes;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the merged active bean definition profiles for the {@link #getTestClass() test class}.
|
* Get the merged {@code ApplicationContextInitializer} classes for the
|
||||||
|
* {@linkplain #getTestClass() test class}.
|
||||||
|
*/
|
||||||
|
public Set<Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>> getContextInitializerClasses() {
|
||||||
|
return contextInitializerClasses;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the merged active bean definition profiles for the {@linkplain #getTestClass() test class}.
|
||||||
*/
|
*/
|
||||||
public String[] getActiveProfiles() {
|
public String[] getActiveProfiles() {
|
||||||
return activeProfiles;
|
return activeProfiles;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the resolved {@link ContextLoader} for the {@link #getTestClass() test class}.
|
* Get the resolved {@link ContextLoader} for the {@linkplain #getTestClass() test class}.
|
||||||
*/
|
*/
|
||||||
public ContextLoader getContextLoader() {
|
public ContextLoader getContextLoader() {
|
||||||
return contextLoader;
|
return contextLoader;
|
||||||
|
@ -159,7 +210,7 @@ public class MergedContextConfiguration implements Serializable {
|
||||||
/**
|
/**
|
||||||
* Generate a unique hash code for all properties of this
|
* Generate a unique hash code for all properties of this
|
||||||
* {@code MergedContextConfiguration} excluding the
|
* {@code MergedContextConfiguration} excluding the
|
||||||
* {@link #getTestClass() test class}.
|
* {@linkplain #getTestClass() test class}.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public int hashCode() {
|
public int hashCode() {
|
||||||
|
@ -167,6 +218,7 @@ public class MergedContextConfiguration implements Serializable {
|
||||||
int result = 1;
|
int result = 1;
|
||||||
result = prime * result + Arrays.hashCode(locations);
|
result = prime * result + Arrays.hashCode(locations);
|
||||||
result = prime * result + Arrays.hashCode(classes);
|
result = prime * result + Arrays.hashCode(classes);
|
||||||
|
result = prime * result + contextInitializerClasses.hashCode();
|
||||||
result = prime * result + Arrays.hashCode(activeProfiles);
|
result = prime * result + Arrays.hashCode(activeProfiles);
|
||||||
result = prime * result + nullSafeToString(contextLoader).hashCode();
|
result = prime * result + nullSafeToString(contextLoader).hashCode();
|
||||||
return result;
|
return result;
|
||||||
|
@ -174,10 +226,11 @@ public class MergedContextConfiguration implements Serializable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine if the supplied object is equal to this {@code MergedContextConfiguration}
|
* Determine if the supplied object is equal to this {@code MergedContextConfiguration}
|
||||||
* instance by comparing both object's {@link #getLocations() locations},
|
* instance by comparing both object's {@linkplain #getLocations() locations},
|
||||||
* {@link #getClasses() annotated classes}, {@link #getActiveProfiles()
|
* {@linkplain #getClasses() annotated classes},
|
||||||
* active profiles}, and the fully qualified names of their
|
* {@linkplain #getContextInitializerClasses() context initializer classes},
|
||||||
* {@link #getContextLoader() ContextLoaders}.
|
* {@linkplain #getActiveProfiles() active profiles}, and the fully qualified
|
||||||
|
* names of their {@link #getContextLoader() ContextLoaders}.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(Object obj) {
|
public boolean equals(Object obj) {
|
||||||
|
@ -197,6 +250,9 @@ public class MergedContextConfiguration implements Serializable {
|
||||||
if (!Arrays.equals(this.classes, that.classes)) {
|
if (!Arrays.equals(this.classes, that.classes)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
if (!this.contextInitializerClasses.equals(that.contextInitializerClasses)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
if (!Arrays.equals(this.activeProfiles, that.activeProfiles)) {
|
if (!Arrays.equals(this.activeProfiles, that.activeProfiles)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -208,9 +264,10 @@ public class MergedContextConfiguration implements Serializable {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provide a String representation of the {@link #getTestClass() test class},
|
* Provide a String representation of the {@linkplain #getTestClass() test class},
|
||||||
* {@link #getLocations() locations}, {@link #getClasses() annotated classes},
|
* {@linkplain #getLocations() locations}, {@linkplain #getClasses() annotated classes},
|
||||||
* {@link #getActiveProfiles() active profiles}, and the name of the
|
* {@linkplain #getContextInitializerClasses() context initializer classes},
|
||||||
|
* {@linkplain #getActiveProfiles() active profiles}, and the name of the
|
||||||
* {@link #getContextLoader() ContextLoader}.
|
* {@link #getContextLoader() ContextLoader}.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
|
@ -219,6 +276,7 @@ public class MergedContextConfiguration implements Serializable {
|
||||||
.append("testClass", testClass)//
|
.append("testClass", testClass)//
|
||||||
.append("locations", ObjectUtils.nullSafeToString(locations))//
|
.append("locations", ObjectUtils.nullSafeToString(locations))//
|
||||||
.append("classes", ObjectUtils.nullSafeToString(classes))//
|
.append("classes", ObjectUtils.nullSafeToString(classes))//
|
||||||
|
.append("contextInitializerClasses", ObjectUtils.nullSafeToString(contextInitializerClasses))//
|
||||||
.append("activeProfiles", ObjectUtils.nullSafeToString(activeProfiles))//
|
.append("activeProfiles", ObjectUtils.nullSafeToString(activeProfiles))//
|
||||||
.append("contextLoader", nullSafeToString(contextLoader))//
|
.append("contextLoader", nullSafeToString(contextLoader))//
|
||||||
.toString();
|
.toString();
|
||||||
|
|
|
@ -16,14 +16,25 @@
|
||||||
|
|
||||||
package org.springframework.test.context.support;
|
package org.springframework.test.context.support;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
|
import org.springframework.beans.BeanUtils;
|
||||||
import org.springframework.beans.factory.support.BeanDefinitionReader;
|
import org.springframework.beans.factory.support.BeanDefinitionReader;
|
||||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
|
||||||
|
import org.springframework.context.ApplicationContextInitializer;
|
||||||
import org.springframework.context.ConfigurableApplicationContext;
|
import org.springframework.context.ConfigurableApplicationContext;
|
||||||
import org.springframework.context.annotation.AnnotationConfigUtils;
|
import org.springframework.context.annotation.AnnotationConfigUtils;
|
||||||
import org.springframework.context.support.GenericApplicationContext;
|
import org.springframework.context.support.GenericApplicationContext;
|
||||||
|
import org.springframework.core.GenericTypeResolver;
|
||||||
|
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
|
||||||
import org.springframework.test.context.MergedContextConfiguration;
|
import org.springframework.test.context.MergedContextConfiguration;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.util.StringUtils;
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -66,11 +77,8 @@ public abstract class AbstractGenericContextLoader extends AbstractContextLoader
|
||||||
*
|
*
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>Creates a {@link GenericApplicationContext} instance.</li>
|
* <li>Creates a {@link GenericApplicationContext} instance.</li>
|
||||||
* <li>Sets the <em>active bean definition profiles</em> from the supplied
|
* <li>Calls {@link #prepareContext(GenericApplicationContext, MergedContextConfiguration)}
|
||||||
* <code>MergedContextConfiguration</code> in the
|
* to allow for customizing the context before bean definitions are loaded.</li>
|
||||||
* {@link org.springframework.core.env.Environment Environment} of the context.</li>
|
|
||||||
* <li>Calls {@link #prepareContext(GenericApplicationContext)} to allow for customizing the context
|
|
||||||
* before bean definitions are loaded.</li>
|
|
||||||
* <li>Calls {@link #customizeBeanFactory(DefaultListableBeanFactory)} to allow for customizing the
|
* <li>Calls {@link #customizeBeanFactory(DefaultListableBeanFactory)} to allow for customizing the
|
||||||
* context's <code>DefaultListableBeanFactory</code>.</li>
|
* context's <code>DefaultListableBeanFactory</code>.</li>
|
||||||
* <li>Delegates to {@link #loadBeanDefinitions(GenericApplicationContext, MergedContextConfiguration)}
|
* <li>Delegates to {@link #loadBeanDefinitions(GenericApplicationContext, MergedContextConfiguration)}
|
||||||
|
@ -95,9 +103,9 @@ public abstract class AbstractGenericContextLoader extends AbstractContextLoader
|
||||||
logger.debug(String.format("Loading ApplicationContext for merged context configuration [%s].",
|
logger.debug(String.format("Loading ApplicationContext for merged context configuration [%s].",
|
||||||
mergedConfig));
|
mergedConfig));
|
||||||
}
|
}
|
||||||
|
|
||||||
GenericApplicationContext context = new GenericApplicationContext();
|
GenericApplicationContext context = new GenericApplicationContext();
|
||||||
context.getEnvironment().setActiveProfiles(mergedConfig.getActiveProfiles());
|
prepareContext(context, mergedConfig);
|
||||||
prepareContext(context);
|
|
||||||
customizeBeanFactory(context.getDefaultListableBeanFactory());
|
customizeBeanFactory(context.getDefaultListableBeanFactory());
|
||||||
loadBeanDefinitions(context, mergedConfig);
|
loadBeanDefinitions(context, mergedConfig);
|
||||||
AnnotationConfigUtils.registerAnnotationConfigProcessors(context);
|
AnnotationConfigUtils.registerAnnotationConfigProcessors(context);
|
||||||
|
@ -132,6 +140,7 @@ public abstract class AbstractGenericContextLoader extends AbstractContextLoader
|
||||||
*
|
*
|
||||||
* <p><b>Note</b>: this method does not provide a means to set active bean definition
|
* <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)}
|
||||||
|
* and {@link #prepareContext(GenericApplicationContext, MergedContextConfiguration)}
|
||||||
* for an alternative.
|
* for an alternative.
|
||||||
*
|
*
|
||||||
* @return a new application context
|
* @return a new application context
|
||||||
|
@ -174,6 +183,72 @@ public abstract class AbstractGenericContextLoader extends AbstractContextLoader
|
||||||
protected void prepareContext(GenericApplicationContext context) {
|
protected void prepareContext(GenericApplicationContext context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepare the {@link GenericApplicationContext} created by this
|
||||||
|
* {@code SmartContextLoader} <i>before</i> bean definitions are read.
|
||||||
|
*
|
||||||
|
* <p>The default implementation:
|
||||||
|
* <ul>
|
||||||
|
* <li>Calls {@link #prepareContext(GenericApplicationContext)} for backwards
|
||||||
|
* compatibility with the {@link org.springframework.test.context.ContextLoader
|
||||||
|
* ContextLoader} SPI.</li>
|
||||||
|
* <li>Sets the <em>active bean definition profiles</em> from the supplied
|
||||||
|
* <code>MergedContextConfiguration</code> in the
|
||||||
|
* {@link org.springframework.core.env.Environment Environment} of the context.</li>
|
||||||
|
* <li>Determines what (if any) context initializer classes have been supplied
|
||||||
|
* via the {@code MergedContextConfiguration} and
|
||||||
|
* {@linkplain ApplicationContextInitializer#initialize invokes each} with the
|
||||||
|
* given application context.</li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* <p>Any {@code ApplicationContextInitializers} implementing
|
||||||
|
* {@link org.springframework.core.Ordered Ordered} or marked with {@link
|
||||||
|
* org.springframework.core.annotation.Order @Order} will be sorted appropriately.
|
||||||
|
*
|
||||||
|
* @param applicationContext the newly created application context
|
||||||
|
* @param mergedConfig the merged context configuration
|
||||||
|
* @see ApplicationContextInitializer#initialize(GenericApplicationContext)
|
||||||
|
* @see #loadContext(MergedContextConfiguration)
|
||||||
|
* @see GenericApplicationContext#setAllowBeanDefinitionOverriding
|
||||||
|
* @see GenericApplicationContext#setResourceLoader
|
||||||
|
* @see GenericApplicationContext#setId
|
||||||
|
* @since 3.2
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
protected void prepareContext(GenericApplicationContext applicationContext,
|
||||||
|
MergedContextConfiguration mergedConfig) {
|
||||||
|
|
||||||
|
prepareContext(applicationContext);
|
||||||
|
|
||||||
|
applicationContext.getEnvironment().setActiveProfiles(mergedConfig.getActiveProfiles());
|
||||||
|
|
||||||
|
Set<Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>> initializerClasses = mergedConfig.getContextInitializerClasses();
|
||||||
|
|
||||||
|
if (initializerClasses.size() == 0) {
|
||||||
|
// no ApplicationContextInitializers have been declared -> nothing to do
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final List<ApplicationContextInitializer<ConfigurableApplicationContext>> initializerInstances = new ArrayList<ApplicationContextInitializer<ConfigurableApplicationContext>>();
|
||||||
|
final Class<?> contextClass = applicationContext.getClass();
|
||||||
|
|
||||||
|
for (Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>> initializerClass : initializerClasses) {
|
||||||
|
Class<?> initializerContextClass = GenericTypeResolver.resolveTypeArgument(initializerClass,
|
||||||
|
ApplicationContextInitializer.class);
|
||||||
|
Assert.isAssignable(initializerContextClass, contextClass, String.format(
|
||||||
|
"Could not add context initializer [%s] since its generic parameter [%s] "
|
||||||
|
+ "is not assignable from the type of application context used by this "
|
||||||
|
+ "context loader [%s]: ", initializerClass.getName(), initializerContextClass.getName(),
|
||||||
|
contextClass.getName()));
|
||||||
|
initializerInstances.add((ApplicationContextInitializer<ConfigurableApplicationContext>) BeanUtils.instantiateClass(initializerClass));
|
||||||
|
}
|
||||||
|
|
||||||
|
Collections.sort(initializerInstances, new AnnotationAwareOrderComparator());
|
||||||
|
for (ApplicationContextInitializer<ConfigurableApplicationContext> initializer : initializerInstances) {
|
||||||
|
initializer.initialize(applicationContext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Customize the internal bean factory of the ApplicationContext created by
|
* Customize the internal bean factory of the ApplicationContext created by
|
||||||
* this <code>ContextLoader</code>.
|
* this <code>ContextLoader</code>.
|
||||||
|
|
|
@ -21,6 +21,7 @@ import java.util.List;
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
import org.springframework.context.ApplicationContext;
|
import org.springframework.context.ApplicationContext;
|
||||||
import org.springframework.test.context.ContextConfiguration;
|
import org.springframework.test.context.ContextConfiguration;
|
||||||
import org.springframework.test.context.ContextConfigurationAttributes;
|
import org.springframework.test.context.ContextConfigurationAttributes;
|
||||||
|
@ -50,6 +51,12 @@ import org.springframework.util.ObjectUtils;
|
||||||
* the default loader, thus providing automatic support for either XML configuration
|
* the default loader, thus providing automatic support for either XML configuration
|
||||||
* files or annotated classes, but not both simultaneously.
|
* files or annotated classes, but not both simultaneously.
|
||||||
*
|
*
|
||||||
|
* <p>As of Spring 3.2, a test class may optionally declare neither XML configuration
|
||||||
|
* files 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 an an exception.
|
||||||
|
*
|
||||||
* @author Sam Brannen
|
* @author Sam Brannen
|
||||||
* @since 3.1
|
* @since 3.1
|
||||||
* @see SmartContextLoader
|
* @see SmartContextLoader
|
||||||
|
@ -78,11 +85,18 @@ public class DelegatingSmartContextLoader implements SmartContextLoader {
|
||||||
loader.processContextConfiguration(configAttributes);
|
loader.processContextConfiguration(configAttributes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static ApplicationContext delegateLoading(SmartContextLoader loader, MergedContextConfiguration mergedConfig)
|
||||||
|
throws Exception {
|
||||||
|
if (logger.isDebugEnabled()) {
|
||||||
|
logger.debug(String.format("Delegating to %s to load context from %s.", name(loader), mergedConfig));
|
||||||
|
}
|
||||||
|
return loader.loadContext(mergedConfig);
|
||||||
|
}
|
||||||
|
|
||||||
private static boolean supports(SmartContextLoader loader, MergedContextConfiguration mergedConfig) {
|
private static boolean supports(SmartContextLoader loader, MergedContextConfiguration mergedConfig) {
|
||||||
if (loader instanceof AnnotationConfigContextLoader) {
|
if (loader instanceof AnnotationConfigContextLoader) {
|
||||||
return ObjectUtils.isEmpty(mergedConfig.getLocations()) && !ObjectUtils.isEmpty(mergedConfig.getClasses());
|
return ObjectUtils.isEmpty(mergedConfig.getLocations()) && !ObjectUtils.isEmpty(mergedConfig.getClasses());
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
return !ObjectUtils.isEmpty(mergedConfig.getLocations()) && ObjectUtils.isEmpty(mergedConfig.getClasses());
|
return !ObjectUtils.isEmpty(mergedConfig.getLocations()) && ObjectUtils.isEmpty(mergedConfig.getClasses());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -132,11 +146,9 @@ public class DelegatingSmartContextLoader implements SmartContextLoader {
|
||||||
// appropriate loader process the configuration.
|
// appropriate loader process the configuration.
|
||||||
if (configAttributes.hasLocations()) {
|
if (configAttributes.hasLocations()) {
|
||||||
delegateProcessing(xmlLoader, configAttributes);
|
delegateProcessing(xmlLoader, configAttributes);
|
||||||
}
|
} else if (configAttributes.hasClasses()) {
|
||||||
else if (configAttributes.hasClasses()) {
|
|
||||||
delegateProcessing(annotationConfigLoader, configAttributes);
|
delegateProcessing(annotationConfigLoader, configAttributes);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
// Else attempt to detect defaults...
|
// Else attempt to detect defaults...
|
||||||
|
|
||||||
// Let the XML loader process the configuration.
|
// Let the XML loader process the configuration.
|
||||||
|
@ -173,10 +185,12 @@ public class DelegatingSmartContextLoader implements SmartContextLoader {
|
||||||
name(annotationConfigLoader), configAttributes));
|
name(annotationConfigLoader), configAttributes));
|
||||||
}
|
}
|
||||||
|
|
||||||
// If neither loader detected defaults, throw an exception.
|
// If neither loader detected defaults and no initializers were declared,
|
||||||
if (!configAttributes.hasResources()) {
|
// throw an exception.
|
||||||
|
if (!configAttributes.hasResources() && ObjectUtils.isEmpty(configAttributes.getInitializers())) {
|
||||||
throw new IllegalStateException(String.format(
|
throw new IllegalStateException(String.format(
|
||||||
"Neither %s nor %s was able to detect defaults for context configuration %s.", name(xmlLoader),
|
"Neither %s nor %s was able to detect defaults, and no ApplicationContextInitializers "
|
||||||
|
+ "were declared for context configuration %s", name(xmlLoader),
|
||||||
name(annotationConfigLoader), configAttributes));
|
name(annotationConfigLoader), configAttributes));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -219,16 +233,19 @@ public class DelegatingSmartContextLoader implements SmartContextLoader {
|
||||||
List<SmartContextLoader> candidates = Arrays.asList(xmlLoader, annotationConfigLoader);
|
List<SmartContextLoader> candidates = Arrays.asList(xmlLoader, annotationConfigLoader);
|
||||||
|
|
||||||
for (SmartContextLoader loader : candidates) {
|
for (SmartContextLoader loader : candidates) {
|
||||||
// Determine if each loader can load a context from the
|
// Determine if each loader can load a context from the mergedConfig. If it
|
||||||
// mergedConfig. If it can, let it; otherwise, keep iterating.
|
// can, let it; otherwise, keep iterating.
|
||||||
if (supports(loader, mergedConfig)) {
|
if (supports(loader, mergedConfig)) {
|
||||||
if (logger.isDebugEnabled()) {
|
return delegateLoading(loader, mergedConfig);
|
||||||
logger.debug(String.format("Delegating to %s to load context from %s.", name(loader), mergedConfig));
|
|
||||||
}
|
|
||||||
return loader.loadContext(mergedConfig);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If neither of the candidates supports the mergedConfig based on resources but
|
||||||
|
// ACIs were declared, then delegate to the ACCL.
|
||||||
|
if (!mergedConfig.getContextInitializerClasses().isEmpty()) {
|
||||||
|
return delegateLoading(annotationConfigLoader, mergedConfig);
|
||||||
|
}
|
||||||
|
|
||||||
throw new IllegalStateException(String.format(
|
throw new IllegalStateException(String.format(
|
||||||
"Neither %s nor %s was able to load an ApplicationContext from %s.", name(xmlLoader),
|
"Neither %s nor %s was able to load an ApplicationContext from %s.", name(xmlLoader),
|
||||||
name(annotationConfigLoader), mergedConfig));
|
name(annotationConfigLoader), mergedConfig));
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2011 the original author or authors.
|
* Copyright 2002-2012 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -16,19 +16,24 @@
|
||||||
|
|
||||||
package org.springframework.test.context;
|
package org.springframework.test.context;
|
||||||
|
|
||||||
import static org.junit.Assert.assertArrayEquals;
|
import static org.springframework.test.context.ContextLoaderUtils.*;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.*;
|
||||||
import static org.junit.Assert.assertNotNull;
|
|
||||||
import static org.junit.Assert.assertTrue;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
import org.springframework.context.ApplicationContextInitializer;
|
||||||
|
import org.springframework.context.ConfigurableApplicationContext;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.context.support.GenericApplicationContext;
|
||||||
import org.springframework.test.context.support.AnnotationConfigContextLoader;
|
import org.springframework.test.context.support.AnnotationConfigContextLoader;
|
||||||
import org.springframework.test.context.support.DelegatingSmartContextLoader;
|
import org.springframework.test.context.support.DelegatingSmartContextLoader;
|
||||||
import org.springframework.test.context.support.GenericPropertiesContextLoader;
|
import org.springframework.test.context.support.GenericPropertiesContextLoader;
|
||||||
|
import org.springframework.web.context.support.GenericWebApplicationContext;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unit tests for {@link ContextLoaderUtils}.
|
* Unit tests for {@link ContextLoaderUtils}.
|
||||||
|
@ -40,6 +45,8 @@ public class ContextLoaderUtilsTests {
|
||||||
|
|
||||||
private static final Class<?>[] EMPTY_CLASS_ARRAY = new Class<?>[0];
|
private static final Class<?>[] EMPTY_CLASS_ARRAY = new Class<?>[0];
|
||||||
private static final String[] EMPTY_STRING_ARRAY = new String[0];
|
private static final String[] EMPTY_STRING_ARRAY = new String[0];
|
||||||
|
private static final Set<Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>> EMPTY_INITIALIZER_CLASSES = //
|
||||||
|
Collections.<Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>> emptySet();
|
||||||
|
|
||||||
|
|
||||||
private void assertAttributes(ContextConfigurationAttributes attributes, Class<?> expectedDeclaringClass,
|
private void assertAttributes(ContextConfigurationAttributes attributes, Class<?> expectedDeclaringClass,
|
||||||
|
@ -72,9 +79,20 @@ public class ContextLoaderUtilsTests {
|
||||||
AnnotationConfigContextLoader.class, true);
|
AnnotationConfigContextLoader.class, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertMergedContextConfiguration(MergedContextConfiguration mergedConfig, Class<?> expectedTestClass,
|
private void assertMergedConfig(MergedContextConfiguration mergedConfig, Class<?> expectedTestClass,
|
||||||
String[] expectedLocations, Class<?>[] expectedClasses,
|
String[] expectedLocations, Class<?>[] expectedClasses,
|
||||||
Class<? extends ContextLoader> expectedContextLoaderClass) {
|
Class<? extends ContextLoader> expectedContextLoaderClass) {
|
||||||
|
assertMergedConfig(mergedConfig, expectedTestClass, expectedLocations, expectedClasses,
|
||||||
|
EMPTY_INITIALIZER_CLASSES, expectedContextLoaderClass);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertMergedConfig(
|
||||||
|
MergedContextConfiguration mergedConfig,
|
||||||
|
Class<?> expectedTestClass,
|
||||||
|
String[] expectedLocations,
|
||||||
|
Class<?>[] expectedClasses,
|
||||||
|
Set<Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>> expectedInitializerClasses,
|
||||||
|
Class<? extends ContextLoader> expectedContextLoaderClass) {
|
||||||
assertNotNull(mergedConfig);
|
assertNotNull(mergedConfig);
|
||||||
assertEquals(expectedTestClass, mergedConfig.getTestClass());
|
assertEquals(expectedTestClass, mergedConfig.getTestClass());
|
||||||
assertNotNull(mergedConfig.getLocations());
|
assertNotNull(mergedConfig.getLocations());
|
||||||
|
@ -83,16 +101,18 @@ public class ContextLoaderUtilsTests {
|
||||||
assertArrayEquals(expectedClasses, mergedConfig.getClasses());
|
assertArrayEquals(expectedClasses, mergedConfig.getClasses());
|
||||||
assertNotNull(mergedConfig.getActiveProfiles());
|
assertNotNull(mergedConfig.getActiveProfiles());
|
||||||
assertEquals(expectedContextLoaderClass, mergedConfig.getContextLoader().getClass());
|
assertEquals(expectedContextLoaderClass, mergedConfig.getContextLoader().getClass());
|
||||||
|
assertNotNull(mergedConfig.getContextInitializerClasses());
|
||||||
|
assertEquals(expectedInitializerClasses, mergedConfig.getContextInitializerClasses());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = IllegalStateException.class)
|
@Test(expected = IllegalStateException.class)
|
||||||
public void resolveContextConfigurationAttributesWithConflictingLocations() {
|
public void resolveConfigAttributesWithConflictingLocations() {
|
||||||
ContextLoaderUtils.resolveContextConfigurationAttributes(ConflictingLocations.class);
|
resolveContextConfigurationAttributes(ConflictingLocations.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void resolveContextConfigurationAttributesWithBareAnnotations() {
|
public void resolveConfigAttributesWithBareAnnotations() {
|
||||||
List<ContextConfigurationAttributes> attributesList = ContextLoaderUtils.resolveContextConfigurationAttributes(BareAnnotations.class);
|
List<ContextConfigurationAttributes> attributesList = resolveContextConfigurationAttributes(BareAnnotations.class);
|
||||||
assertNotNull(attributesList);
|
assertNotNull(attributesList);
|
||||||
assertEquals(1, attributesList.size());
|
assertEquals(1, attributesList.size());
|
||||||
assertAttributes(attributesList.get(0), BareAnnotations.class, EMPTY_STRING_ARRAY, EMPTY_CLASS_ARRAY,
|
assertAttributes(attributesList.get(0), BareAnnotations.class, EMPTY_STRING_ARRAY, EMPTY_CLASS_ARRAY,
|
||||||
|
@ -100,24 +120,24 @@ public class ContextLoaderUtilsTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void resolveContextConfigurationAttributesWithLocalAnnotationAndLocations() {
|
public void resolveConfigAttributesWithLocalAnnotationAndLocations() {
|
||||||
List<ContextConfigurationAttributes> attributesList = ContextLoaderUtils.resolveContextConfigurationAttributes(LocationsFoo.class);
|
List<ContextConfigurationAttributes> attributesList = resolveContextConfigurationAttributes(LocationsFoo.class);
|
||||||
assertNotNull(attributesList);
|
assertNotNull(attributesList);
|
||||||
assertEquals(1, attributesList.size());
|
assertEquals(1, attributesList.size());
|
||||||
assertLocationsFooAttributes(attributesList.get(0));
|
assertLocationsFooAttributes(attributesList.get(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void resolveContextConfigurationAttributesWithLocalAnnotationAndClasses() {
|
public void resolveConfigAttributesWithLocalAnnotationAndClasses() {
|
||||||
List<ContextConfigurationAttributes> attributesList = ContextLoaderUtils.resolveContextConfigurationAttributes(ClassesFoo.class);
|
List<ContextConfigurationAttributes> attributesList = resolveContextConfigurationAttributes(ClassesFoo.class);
|
||||||
assertNotNull(attributesList);
|
assertNotNull(attributesList);
|
||||||
assertEquals(1, attributesList.size());
|
assertEquals(1, attributesList.size());
|
||||||
assertClassesFooAttributes(attributesList.get(0));
|
assertClassesFooAttributes(attributesList.get(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void resolveContextConfigurationAttributesWithLocalAndInheritedAnnotationsAndLocations() {
|
public void resolveConfigAttributesWithLocalAndInheritedAnnotationsAndLocations() {
|
||||||
List<ContextConfigurationAttributes> attributesList = ContextLoaderUtils.resolveContextConfigurationAttributes(LocationsBar.class);
|
List<ContextConfigurationAttributes> attributesList = resolveContextConfigurationAttributes(LocationsBar.class);
|
||||||
assertNotNull(attributesList);
|
assertNotNull(attributesList);
|
||||||
assertEquals(2, attributesList.size());
|
assertEquals(2, attributesList.size());
|
||||||
assertLocationsFooAttributes(attributesList.get(0));
|
assertLocationsFooAttributes(attributesList.get(0));
|
||||||
|
@ -125,8 +145,8 @@ public class ContextLoaderUtilsTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void resolveContextConfigurationAttributesWithLocalAndInheritedAnnotationsAndClasses() {
|
public void resolveConfigAttributesWithLocalAndInheritedAnnotationsAndClasses() {
|
||||||
List<ContextConfigurationAttributes> attributesList = ContextLoaderUtils.resolveContextConfigurationAttributes(ClassesBar.class);
|
List<ContextConfigurationAttributes> attributesList = resolveContextConfigurationAttributes(ClassesBar.class);
|
||||||
assertNotNull(attributesList);
|
assertNotNull(attributesList);
|
||||||
assertEquals(2, attributesList.size());
|
assertEquals(2, attributesList.size());
|
||||||
assertClassesFooAttributes(attributesList.get(0));
|
assertClassesFooAttributes(attributesList.get(0));
|
||||||
|
@ -134,16 +154,16 @@ public class ContextLoaderUtilsTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = IllegalArgumentException.class)
|
@Test(expected = IllegalArgumentException.class)
|
||||||
public void buildMergedContextConfigurationWithoutAnnotation() {
|
public void buildMergedConfigWithoutAnnotation() {
|
||||||
ContextLoaderUtils.buildMergedContextConfiguration(Enigma.class, null);
|
buildMergedContextConfiguration(Enigma.class, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void buildMergedContextConfigurationWithBareAnnotations() {
|
public void buildMergedConfigWithBareAnnotations() {
|
||||||
Class<BareAnnotations> testClass = BareAnnotations.class;
|
Class<BareAnnotations> testClass = BareAnnotations.class;
|
||||||
MergedContextConfiguration mergedConfig = ContextLoaderUtils.buildMergedContextConfiguration(testClass, null);
|
MergedContextConfiguration mergedConfig = buildMergedContextConfiguration(testClass, null);
|
||||||
|
|
||||||
assertMergedContextConfiguration(
|
assertMergedConfig(
|
||||||
mergedConfig,
|
mergedConfig,
|
||||||
testClass,
|
testClass,
|
||||||
new String[] { "classpath:/org/springframework/test/context/ContextLoaderUtilsTests$BareAnnotations-context.xml" },
|
new String[] { "classpath:/org/springframework/test/context/ContextLoaderUtilsTests$BareAnnotations-context.xml" },
|
||||||
|
@ -151,86 +171,159 @@ public class ContextLoaderUtilsTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void buildMergedContextConfigurationWithLocalAnnotationAndLocations() {
|
public void buildMergedConfigWithLocalAnnotationAndLocations() {
|
||||||
Class<?> testClass = LocationsFoo.class;
|
Class<?> testClass = LocationsFoo.class;
|
||||||
MergedContextConfiguration mergedConfig = ContextLoaderUtils.buildMergedContextConfiguration(testClass, null);
|
MergedContextConfiguration mergedConfig = buildMergedContextConfiguration(testClass, null);
|
||||||
|
|
||||||
assertMergedContextConfiguration(mergedConfig, testClass, new String[] { "classpath:/foo.xml" },
|
assertMergedConfig(mergedConfig, testClass, new String[] { "classpath:/foo.xml" }, EMPTY_CLASS_ARRAY,
|
||||||
EMPTY_CLASS_ARRAY, DelegatingSmartContextLoader.class);
|
DelegatingSmartContextLoader.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void buildMergedContextConfigurationWithLocalAnnotationAndClasses() {
|
public void buildMergedConfigWithLocalAnnotationAndClasses() {
|
||||||
Class<?> testClass = ClassesFoo.class;
|
Class<?> testClass = ClassesFoo.class;
|
||||||
MergedContextConfiguration mergedConfig = ContextLoaderUtils.buildMergedContextConfiguration(testClass, null);
|
MergedContextConfiguration mergedConfig = buildMergedContextConfiguration(testClass, null);
|
||||||
|
|
||||||
assertMergedContextConfiguration(mergedConfig, testClass, EMPTY_STRING_ARRAY,
|
assertMergedConfig(mergedConfig, testClass, EMPTY_STRING_ARRAY, new Class<?>[] { FooConfig.class },
|
||||||
new Class<?>[] { FooConfig.class }, DelegatingSmartContextLoader.class);
|
DelegatingSmartContextLoader.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void buildMergedContextConfigurationWithLocalAnnotationAndOverriddenContextLoaderAndLocations() {
|
public void buildMergedConfigWithLocalAnnotationAndOverriddenContextLoaderAndLocations() {
|
||||||
Class<?> testClass = LocationsFoo.class;
|
Class<?> testClass = LocationsFoo.class;
|
||||||
Class<? extends ContextLoader> expectedContextLoaderClass = GenericPropertiesContextLoader.class;
|
Class<? extends ContextLoader> expectedContextLoaderClass = GenericPropertiesContextLoader.class;
|
||||||
MergedContextConfiguration mergedConfig = ContextLoaderUtils.buildMergedContextConfiguration(testClass,
|
MergedContextConfiguration mergedConfig = buildMergedContextConfiguration(testClass,
|
||||||
expectedContextLoaderClass.getName());
|
expectedContextLoaderClass.getName());
|
||||||
|
|
||||||
assertMergedContextConfiguration(mergedConfig, testClass, new String[] { "classpath:/foo.xml" },
|
assertMergedConfig(mergedConfig, testClass, new String[] { "classpath:/foo.xml" }, EMPTY_CLASS_ARRAY,
|
||||||
EMPTY_CLASS_ARRAY, expectedContextLoaderClass);
|
expectedContextLoaderClass);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void buildMergedContextConfigurationWithLocalAnnotationAndOverriddenContextLoaderAndClasses() {
|
public void buildMergedConfigWithLocalAnnotationAndOverriddenContextLoaderAndClasses() {
|
||||||
Class<?> testClass = ClassesFoo.class;
|
Class<?> testClass = ClassesFoo.class;
|
||||||
Class<? extends ContextLoader> expectedContextLoaderClass = GenericPropertiesContextLoader.class;
|
Class<? extends ContextLoader> expectedContextLoaderClass = GenericPropertiesContextLoader.class;
|
||||||
MergedContextConfiguration mergedConfig = ContextLoaderUtils.buildMergedContextConfiguration(testClass,
|
MergedContextConfiguration mergedConfig = buildMergedContextConfiguration(testClass,
|
||||||
expectedContextLoaderClass.getName());
|
expectedContextLoaderClass.getName());
|
||||||
|
|
||||||
assertMergedContextConfiguration(mergedConfig, testClass, EMPTY_STRING_ARRAY,
|
assertMergedConfig(mergedConfig, testClass, EMPTY_STRING_ARRAY, new Class<?>[] { FooConfig.class },
|
||||||
new Class<?>[] { FooConfig.class }, expectedContextLoaderClass);
|
expectedContextLoaderClass);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void buildMergedContextConfigurationWithLocalAndInheritedAnnotationsAndLocations() {
|
public void buildMergedConfigWithLocalAndInheritedAnnotationsAndLocations() {
|
||||||
Class<?> testClass = LocationsBar.class;
|
Class<?> testClass = LocationsBar.class;
|
||||||
String[] expectedLocations = new String[] { "/foo.xml", "/bar.xml" };
|
String[] expectedLocations = new String[] { "/foo.xml", "/bar.xml" };
|
||||||
|
|
||||||
MergedContextConfiguration mergedConfig = ContextLoaderUtils.buildMergedContextConfiguration(testClass, null);
|
MergedContextConfiguration mergedConfig = buildMergedContextConfiguration(testClass, null);
|
||||||
assertMergedContextConfiguration(mergedConfig, testClass, expectedLocations, EMPTY_CLASS_ARRAY,
|
assertMergedConfig(mergedConfig, testClass, expectedLocations, EMPTY_CLASS_ARRAY,
|
||||||
AnnotationConfigContextLoader.class);
|
AnnotationConfigContextLoader.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void buildMergedContextConfigurationWithLocalAndInheritedAnnotationsAndClasses() {
|
public void buildMergedConfigWithLocalAndInheritedAnnotationsAndClasses() {
|
||||||
Class<?> testClass = ClassesBar.class;
|
Class<?> testClass = ClassesBar.class;
|
||||||
Class<?>[] expectedClasses = new Class<?>[] { FooConfig.class, BarConfig.class };
|
Class<?>[] expectedClasses = new Class<?>[] { FooConfig.class, BarConfig.class };
|
||||||
|
|
||||||
MergedContextConfiguration mergedConfig = ContextLoaderUtils.buildMergedContextConfiguration(testClass, null);
|
MergedContextConfiguration mergedConfig = buildMergedContextConfiguration(testClass, null);
|
||||||
assertMergedContextConfiguration(mergedConfig, testClass, EMPTY_STRING_ARRAY, expectedClasses,
|
assertMergedConfig(mergedConfig, testClass, EMPTY_STRING_ARRAY, expectedClasses,
|
||||||
AnnotationConfigContextLoader.class);
|
AnnotationConfigContextLoader.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void buildMergedConfigWithAnnotationsAndOverriddenLocations() {
|
||||||
|
Class<?> testClass = OverriddenLocationsBar.class;
|
||||||
|
String[] expectedLocations = new String[] { "/bar.xml" };
|
||||||
|
|
||||||
|
MergedContextConfiguration mergedConfig = buildMergedContextConfiguration(testClass, null);
|
||||||
|
assertMergedConfig(mergedConfig, testClass, expectedLocations, EMPTY_CLASS_ARRAY,
|
||||||
|
AnnotationConfigContextLoader.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void buildMergedConfigWithAnnotationsAndOverriddenClasses() {
|
||||||
|
Class<?> testClass = OverriddenClassesBar.class;
|
||||||
|
Class<?>[] expectedClasses = new Class<?>[] { BarConfig.class };
|
||||||
|
|
||||||
|
MergedContextConfiguration mergedConfig = buildMergedContextConfiguration(testClass, null);
|
||||||
|
assertMergedConfig(mergedConfig, testClass, EMPTY_STRING_ARRAY, expectedClasses,
|
||||||
|
AnnotationConfigContextLoader.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void buildMergedConfigWithLocalInitializer() {
|
||||||
|
Class<?> testClass = InitializersFoo.class;
|
||||||
|
Class<?>[] expectedClasses = new Class<?>[] { FooConfig.class };
|
||||||
|
Set<Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>> expectedInitializerClasses//
|
||||||
|
= new HashSet<Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>>();
|
||||||
|
expectedInitializerClasses.add(FooInitializer.class);
|
||||||
|
|
||||||
|
MergedContextConfiguration mergedConfig = buildMergedContextConfiguration(testClass, null);
|
||||||
|
assertMergedConfig(mergedConfig, testClass, EMPTY_STRING_ARRAY, expectedClasses, expectedInitializerClasses,
|
||||||
|
DelegatingSmartContextLoader.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void buildMergedConfigWithLocalAndInheritedInitializer() {
|
||||||
|
Class<?> testClass = InitializersBar.class;
|
||||||
|
Class<?>[] expectedClasses = new Class<?>[] { FooConfig.class, BarConfig.class };
|
||||||
|
Set<Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>> expectedInitializerClasses//
|
||||||
|
= new HashSet<Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>>();
|
||||||
|
expectedInitializerClasses.add(FooInitializer.class);
|
||||||
|
expectedInitializerClasses.add(BarInitializer.class);
|
||||||
|
|
||||||
|
MergedContextConfiguration mergedConfig = buildMergedContextConfiguration(testClass, null);
|
||||||
|
assertMergedConfig(mergedConfig, testClass, EMPTY_STRING_ARRAY, expectedClasses, expectedInitializerClasses,
|
||||||
|
DelegatingSmartContextLoader.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void buildMergedConfigWithOverriddenInitializers() {
|
||||||
|
Class<?> testClass = OverriddenInitializersBar.class;
|
||||||
|
Class<?>[] expectedClasses = new Class<?>[] { FooConfig.class, BarConfig.class };
|
||||||
|
Set<Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>> expectedInitializerClasses//
|
||||||
|
= new HashSet<Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>>();
|
||||||
|
expectedInitializerClasses.add(BarInitializer.class);
|
||||||
|
|
||||||
|
MergedContextConfiguration mergedConfig = buildMergedContextConfiguration(testClass, null);
|
||||||
|
assertMergedConfig(mergedConfig, testClass, EMPTY_STRING_ARRAY, expectedClasses, expectedInitializerClasses,
|
||||||
|
DelegatingSmartContextLoader.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void buildMergedConfigWithOverriddenInitializersAndClasses() {
|
||||||
|
Class<?> testClass = OverriddenInitializersAndClassesBar.class;
|
||||||
|
Class<?>[] expectedClasses = new Class<?>[] { BarConfig.class };
|
||||||
|
Set<Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>> expectedInitializerClasses//
|
||||||
|
= new HashSet<Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>>();
|
||||||
|
expectedInitializerClasses.add(BarInitializer.class);
|
||||||
|
|
||||||
|
MergedContextConfiguration mergedConfig = buildMergedContextConfiguration(testClass, null);
|
||||||
|
assertMergedConfig(mergedConfig, testClass, EMPTY_STRING_ARRAY, expectedClasses, expectedInitializerClasses,
|
||||||
|
DelegatingSmartContextLoader.class);
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void resolveActiveProfilesWithoutAnnotation() {
|
public void resolveActiveProfilesWithoutAnnotation() {
|
||||||
String[] profiles = ContextLoaderUtils.resolveActiveProfiles(Enigma.class);
|
String[] profiles = resolveActiveProfiles(Enigma.class);
|
||||||
assertArrayEquals(EMPTY_STRING_ARRAY, profiles);
|
assertArrayEquals(EMPTY_STRING_ARRAY, profiles);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void resolveActiveProfilesWithNoProfilesDeclared() {
|
public void resolveActiveProfilesWithNoProfilesDeclared() {
|
||||||
String[] profiles = ContextLoaderUtils.resolveActiveProfiles(BareAnnotations.class);
|
String[] profiles = resolveActiveProfiles(BareAnnotations.class);
|
||||||
assertArrayEquals(EMPTY_STRING_ARRAY, profiles);
|
assertArrayEquals(EMPTY_STRING_ARRAY, profiles);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void resolveActiveProfilesWithEmptyProfiles() {
|
public void resolveActiveProfilesWithEmptyProfiles() {
|
||||||
String[] profiles = ContextLoaderUtils.resolveActiveProfiles(EmptyProfiles.class);
|
String[] profiles = resolveActiveProfiles(EmptyProfiles.class);
|
||||||
assertArrayEquals(EMPTY_STRING_ARRAY, profiles);
|
assertArrayEquals(EMPTY_STRING_ARRAY, profiles);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void resolveActiveProfilesWithDuplicatedProfiles() {
|
public void resolveActiveProfilesWithDuplicatedProfiles() {
|
||||||
String[] profiles = ContextLoaderUtils.resolveActiveProfiles(DuplicatedProfiles.class);
|
String[] profiles = resolveActiveProfiles(DuplicatedProfiles.class);
|
||||||
assertNotNull(profiles);
|
assertNotNull(profiles);
|
||||||
assertEquals(3, profiles.length);
|
assertEquals(3, profiles.length);
|
||||||
|
|
||||||
|
@ -242,28 +335,28 @@ public class ContextLoaderUtilsTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void resolveActiveProfilesWithLocalAnnotation() {
|
public void resolveActiveProfilesWithLocalAnnotation() {
|
||||||
String[] profiles = ContextLoaderUtils.resolveActiveProfiles(LocationsFoo.class);
|
String[] profiles = resolveActiveProfiles(LocationsFoo.class);
|
||||||
assertNotNull(profiles);
|
assertNotNull(profiles);
|
||||||
assertArrayEquals(new String[] { "foo" }, profiles);
|
assertArrayEquals(new String[] { "foo" }, profiles);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void resolveActiveProfilesWithInheritedAnnotationAndLocations() {
|
public void resolveActiveProfilesWithInheritedAnnotationAndLocations() {
|
||||||
String[] profiles = ContextLoaderUtils.resolveActiveProfiles(InheritedLocationsFoo.class);
|
String[] profiles = resolveActiveProfiles(InheritedLocationsFoo.class);
|
||||||
assertNotNull(profiles);
|
assertNotNull(profiles);
|
||||||
assertArrayEquals(new String[] { "foo" }, profiles);
|
assertArrayEquals(new String[] { "foo" }, profiles);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void resolveActiveProfilesWithInheritedAnnotationAndClasses() {
|
public void resolveActiveProfilesWithInheritedAnnotationAndClasses() {
|
||||||
String[] profiles = ContextLoaderUtils.resolveActiveProfiles(InheritedClassesFoo.class);
|
String[] profiles = resolveActiveProfiles(InheritedClassesFoo.class);
|
||||||
assertNotNull(profiles);
|
assertNotNull(profiles);
|
||||||
assertArrayEquals(new String[] { "foo" }, profiles);
|
assertArrayEquals(new String[] { "foo" }, profiles);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void resolveActiveProfilesWithLocalAndInheritedAnnotations() {
|
public void resolveActiveProfilesWithLocalAndInheritedAnnotations() {
|
||||||
String[] profiles = ContextLoaderUtils.resolveActiveProfiles(LocationsBar.class);
|
String[] profiles = resolveActiveProfiles(LocationsBar.class);
|
||||||
assertNotNull(profiles);
|
assertNotNull(profiles);
|
||||||
assertEquals(2, profiles.length);
|
assertEquals(2, profiles.length);
|
||||||
|
|
||||||
|
@ -274,7 +367,7 @@ public class ContextLoaderUtilsTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void resolveActiveProfilesWithOverriddenAnnotation() {
|
public void resolveActiveProfilesWithOverriddenAnnotation() {
|
||||||
String[] profiles = ContextLoaderUtils.resolveActiveProfiles(Animals.class);
|
String[] profiles = resolveActiveProfiles(Animals.class);
|
||||||
assertNotNull(profiles);
|
assertNotNull(profiles);
|
||||||
assertEquals(2, profiles.length);
|
assertEquals(2, profiles.length);
|
||||||
|
|
||||||
|
@ -333,13 +426,51 @@ public class ContextLoaderUtilsTests {
|
||||||
private static class LocationsBar extends LocationsFoo {
|
private static class LocationsBar extends LocationsFoo {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ContextConfiguration(locations = "/bar.xml", inheritLocations = false, loader = AnnotationConfigContextLoader.class)
|
||||||
|
@ActiveProfiles("bar")
|
||||||
|
private static class OverriddenLocationsBar extends LocationsFoo {
|
||||||
|
}
|
||||||
|
|
||||||
@ContextConfiguration(classes = BarConfig.class, inheritLocations = true, loader = AnnotationConfigContextLoader.class)
|
@ContextConfiguration(classes = BarConfig.class, inheritLocations = true, loader = AnnotationConfigContextLoader.class)
|
||||||
@ActiveProfiles("bar")
|
@ActiveProfiles("bar")
|
||||||
private static class ClassesBar extends ClassesFoo {
|
private static class ClassesBar extends ClassesFoo {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ContextConfiguration(classes = BarConfig.class, inheritLocations = false, loader = AnnotationConfigContextLoader.class)
|
||||||
|
@ActiveProfiles("bar")
|
||||||
|
private static class OverriddenClassesBar extends ClassesFoo {
|
||||||
|
}
|
||||||
|
|
||||||
@ActiveProfiles(profiles = { "dog", "cat" }, inheritProfiles = false)
|
@ActiveProfiles(profiles = { "dog", "cat" }, inheritProfiles = false)
|
||||||
private static class Animals extends LocationsBar {
|
private static class Animals extends LocationsBar {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class FooInitializer implements ApplicationContextInitializer<GenericApplicationContext> {
|
||||||
|
|
||||||
|
public void initialize(GenericApplicationContext applicationContext) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class BarInitializer implements ApplicationContextInitializer<GenericWebApplicationContext> {
|
||||||
|
|
||||||
|
public void initialize(GenericWebApplicationContext applicationContext) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ContextConfiguration(classes = FooConfig.class, initializers = FooInitializer.class)
|
||||||
|
private static class InitializersFoo {
|
||||||
|
}
|
||||||
|
|
||||||
|
@ContextConfiguration(classes = BarConfig.class, initializers = BarInitializer.class)
|
||||||
|
private static class InitializersBar extends InitializersFoo {
|
||||||
|
}
|
||||||
|
|
||||||
|
@ContextConfiguration(classes = BarConfig.class, initializers = BarInitializer.class, inheritInitializers = false)
|
||||||
|
private static class OverriddenInitializersBar extends InitializersFoo {
|
||||||
|
}
|
||||||
|
|
||||||
|
@ContextConfiguration(classes = BarConfig.class, inheritLocations = false, initializers = BarInitializer.class, inheritInitializers = false)
|
||||||
|
private static class OverriddenInitializersAndClassesBar extends InitializersFoo {
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2011 the original author or authors.
|
* Copyright 2002-2012 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
@ -16,17 +16,25 @@
|
||||||
|
|
||||||
package org.springframework.test.context;
|
package org.springframework.test.context;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.*;
|
||||||
import static org.junit.Assert.assertFalse;
|
|
||||||
import static org.junit.Assert.assertTrue;
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import org.springframework.context.ApplicationContextInitializer;
|
||||||
|
import org.springframework.context.ConfigurableApplicationContext;
|
||||||
|
import org.springframework.context.support.GenericApplicationContext;
|
||||||
import org.springframework.test.context.support.AnnotationConfigContextLoader;
|
import org.springframework.test.context.support.AnnotationConfigContextLoader;
|
||||||
import org.springframework.test.context.support.GenericXmlContextLoader;
|
import org.springframework.test.context.support.GenericXmlContextLoader;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unit tests for {@link MergedContextConfiguration}.
|
* Unit tests for {@link MergedContextConfiguration}.
|
||||||
*
|
*
|
||||||
|
* <p>These tests primarily exist to ensure that {@code MergedContextConfiguration}
|
||||||
|
* can safely be used as the cache key for {@link ContextCache}.
|
||||||
|
*
|
||||||
* @author Sam Brannen
|
* @author Sam Brannen
|
||||||
* @since 3.1
|
* @since 3.1
|
||||||
*/
|
*/
|
||||||
|
@ -42,6 +50,7 @@ public class MergedContextConfigurationTests {
|
||||||
public void hashCodeWithNulls() {
|
public void hashCodeWithNulls() {
|
||||||
MergedContextConfiguration mergedConfig1 = new MergedContextConfiguration(null, null, null, null, null);
|
MergedContextConfiguration mergedConfig1 = new MergedContextConfiguration(null, null, null, null, null);
|
||||||
MergedContextConfiguration mergedConfig2 = new MergedContextConfiguration(null, null, null, null, null);
|
MergedContextConfiguration mergedConfig2 = new MergedContextConfiguration(null, null, null, null, null);
|
||||||
|
assertTrue(mergedConfig1.hashCode() > 0);
|
||||||
assertEquals(mergedConfig1.hashCode(), mergedConfig2.hashCode());
|
assertEquals(mergedConfig1.hashCode(), mergedConfig2.hashCode());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -155,6 +164,42 @@ public class MergedContextConfigurationTests {
|
||||||
assertFalse(mergedConfig1.hashCode() == mergedConfig2.hashCode());
|
assertFalse(mergedConfig1.hashCode() == mergedConfig2.hashCode());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void hashCodeWithSameInitializers() {
|
||||||
|
Set<Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>> initializerClasses1 = //
|
||||||
|
new HashSet<Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>>();
|
||||||
|
initializerClasses1.add(FooInitializer.class);
|
||||||
|
initializerClasses1.add(BarInitializer.class);
|
||||||
|
|
||||||
|
Set<Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>> initializerClasses2 = //
|
||||||
|
new HashSet<Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>>();
|
||||||
|
initializerClasses2.add(BarInitializer.class);
|
||||||
|
initializerClasses2.add(FooInitializer.class);
|
||||||
|
|
||||||
|
MergedContextConfiguration mergedConfig1 = new MergedContextConfiguration(getClass(), EMPTY_STRING_ARRAY,
|
||||||
|
EMPTY_CLASS_ARRAY, initializerClasses1, EMPTY_STRING_ARRAY, loader);
|
||||||
|
MergedContextConfiguration mergedConfig2 = new MergedContextConfiguration(getClass(), EMPTY_STRING_ARRAY,
|
||||||
|
EMPTY_CLASS_ARRAY, initializerClasses2, EMPTY_STRING_ARRAY, loader);
|
||||||
|
assertEquals(mergedConfig1.hashCode(), mergedConfig2.hashCode());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void hashCodeWithDifferentInitializers() {
|
||||||
|
Set<Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>> initializerClasses1 = //
|
||||||
|
new HashSet<Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>>();
|
||||||
|
initializerClasses1.add(FooInitializer.class);
|
||||||
|
|
||||||
|
Set<Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>> initializerClasses2 = //
|
||||||
|
new HashSet<Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>>();
|
||||||
|
initializerClasses2.add(BarInitializer.class);
|
||||||
|
|
||||||
|
MergedContextConfiguration mergedConfig1 = new MergedContextConfiguration(getClass(), EMPTY_STRING_ARRAY,
|
||||||
|
EMPTY_CLASS_ARRAY, initializerClasses1, EMPTY_STRING_ARRAY, loader);
|
||||||
|
MergedContextConfiguration mergedConfig2 = new MergedContextConfiguration(getClass(), EMPTY_STRING_ARRAY,
|
||||||
|
EMPTY_CLASS_ARRAY, initializerClasses2, EMPTY_STRING_ARRAY, loader);
|
||||||
|
assertFalse(mergedConfig1.hashCode() == mergedConfig2.hashCode());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void equalsBasics() {
|
public void equalsBasics() {
|
||||||
MergedContextConfiguration mergedConfig = new MergedContextConfiguration(null, null, null, null, null);
|
MergedContextConfiguration mergedConfig = new MergedContextConfiguration(null, null, null, null, null);
|
||||||
|
@ -193,6 +238,7 @@ public class MergedContextConfigurationTests {
|
||||||
MergedContextConfiguration mergedConfig2 = new MergedContextConfiguration(getClass(), EMPTY_STRING_ARRAY,
|
MergedContextConfiguration mergedConfig2 = new MergedContextConfiguration(getClass(), EMPTY_STRING_ARRAY,
|
||||||
EMPTY_CLASS_ARRAY, EMPTY_STRING_ARRAY, new AnnotationConfigContextLoader());
|
EMPTY_CLASS_ARRAY, EMPTY_STRING_ARRAY, new AnnotationConfigContextLoader());
|
||||||
assertFalse(mergedConfig1.equals(mergedConfig2));
|
assertFalse(mergedConfig1.equals(mergedConfig2));
|
||||||
|
assertFalse(mergedConfig2.equals(mergedConfig1));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -214,6 +260,7 @@ public class MergedContextConfigurationTests {
|
||||||
MergedContextConfiguration mergedConfig2 = new MergedContextConfiguration(getClass(), locations2,
|
MergedContextConfiguration mergedConfig2 = new MergedContextConfiguration(getClass(), locations2,
|
||||||
EMPTY_CLASS_ARRAY, EMPTY_STRING_ARRAY, loader);
|
EMPTY_CLASS_ARRAY, EMPTY_STRING_ARRAY, loader);
|
||||||
assertFalse(mergedConfig1.equals(mergedConfig2));
|
assertFalse(mergedConfig1.equals(mergedConfig2));
|
||||||
|
assertFalse(mergedConfig2.equals(mergedConfig1));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -235,6 +282,7 @@ public class MergedContextConfigurationTests {
|
||||||
MergedContextConfiguration mergedConfig2 = new MergedContextConfiguration(getClass(), EMPTY_STRING_ARRAY,
|
MergedContextConfiguration mergedConfig2 = new MergedContextConfiguration(getClass(), EMPTY_STRING_ARRAY,
|
||||||
classes2, EMPTY_STRING_ARRAY, loader);
|
classes2, EMPTY_STRING_ARRAY, loader);
|
||||||
assertFalse(mergedConfig1.equals(mergedConfig2));
|
assertFalse(mergedConfig1.equals(mergedConfig2));
|
||||||
|
assertFalse(mergedConfig2.equals(mergedConfig1));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -278,6 +326,57 @@ public class MergedContextConfigurationTests {
|
||||||
MergedContextConfiguration mergedConfig2 = new MergedContextConfiguration(getClass(), EMPTY_STRING_ARRAY,
|
MergedContextConfiguration mergedConfig2 = new MergedContextConfiguration(getClass(), EMPTY_STRING_ARRAY,
|
||||||
EMPTY_CLASS_ARRAY, activeProfiles2, loader);
|
EMPTY_CLASS_ARRAY, activeProfiles2, loader);
|
||||||
assertFalse(mergedConfig1.equals(mergedConfig2));
|
assertFalse(mergedConfig1.equals(mergedConfig2));
|
||||||
|
assertFalse(mergedConfig2.equals(mergedConfig1));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void equalsWithSameInitializers() {
|
||||||
|
Set<Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>> initializerClasses1 = //
|
||||||
|
new HashSet<Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>>();
|
||||||
|
initializerClasses1.add(FooInitializer.class);
|
||||||
|
initializerClasses1.add(BarInitializer.class);
|
||||||
|
|
||||||
|
Set<Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>> initializerClasses2 = //
|
||||||
|
new HashSet<Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>>();
|
||||||
|
initializerClasses2.add(BarInitializer.class);
|
||||||
|
initializerClasses2.add(FooInitializer.class);
|
||||||
|
|
||||||
|
MergedContextConfiguration mergedConfig1 = new MergedContextConfiguration(getClass(), EMPTY_STRING_ARRAY,
|
||||||
|
EMPTY_CLASS_ARRAY, initializerClasses1, EMPTY_STRING_ARRAY, loader);
|
||||||
|
MergedContextConfiguration mergedConfig2 = new MergedContextConfiguration(getClass(), EMPTY_STRING_ARRAY,
|
||||||
|
EMPTY_CLASS_ARRAY, initializerClasses2, EMPTY_STRING_ARRAY, loader);
|
||||||
|
assertEquals(mergedConfig1, mergedConfig2);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void equalsWithDifferentInitializers() {
|
||||||
|
Set<Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>> initializerClasses1 = //
|
||||||
|
new HashSet<Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>>();
|
||||||
|
initializerClasses1.add(FooInitializer.class);
|
||||||
|
|
||||||
|
Set<Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>> initializerClasses2 = //
|
||||||
|
new HashSet<Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>>();
|
||||||
|
initializerClasses2.add(BarInitializer.class);
|
||||||
|
|
||||||
|
MergedContextConfiguration mergedConfig1 = new MergedContextConfiguration(getClass(), EMPTY_STRING_ARRAY,
|
||||||
|
EMPTY_CLASS_ARRAY, initializerClasses1, EMPTY_STRING_ARRAY, loader);
|
||||||
|
MergedContextConfiguration mergedConfig2 = new MergedContextConfiguration(getClass(), EMPTY_STRING_ARRAY,
|
||||||
|
EMPTY_CLASS_ARRAY, initializerClasses2, EMPTY_STRING_ARRAY, loader);
|
||||||
|
assertFalse(mergedConfig1.equals(mergedConfig2));
|
||||||
|
assertFalse(mergedConfig2.equals(mergedConfig1));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static class FooInitializer implements ApplicationContextInitializer<GenericApplicationContext> {
|
||||||
|
|
||||||
|
public void initialize(GenericApplicationContext applicationContext) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class BarInitializer implements ApplicationContextInitializer<GenericApplicationContext> {
|
||||||
|
|
||||||
|
public void initialize(GenericApplicationContext applicationContext) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2002-2012 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.test.context.junit4.aci;
|
||||||
|
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.junit.runners.Suite;
|
||||||
|
import org.junit.runners.Suite.SuiteClasses;
|
||||||
|
import org.springframework.context.ApplicationContextInitializer;
|
||||||
|
import org.springframework.test.context.junit4.aci.annotation.InitializerWithoutConfigFilesOrClassesTest;
|
||||||
|
import org.springframework.test.context.junit4.aci.annotation.MergedInitializersAnnotationConfigTests;
|
||||||
|
import org.springframework.test.context.junit4.aci.annotation.MultipleInitializersAnnotationConfigTests;
|
||||||
|
import org.springframework.test.context.junit4.aci.annotation.OrderedInitializersAnnotationConfigTests;
|
||||||
|
import org.springframework.test.context.junit4.aci.annotation.OverriddenInitializersAnnotationConfigTests;
|
||||||
|
import org.springframework.test.context.junit4.aci.annotation.SingleInitializerAnnotationConfigTests;
|
||||||
|
import org.springframework.test.context.junit4.aci.xml.MultipleInitializersXmlConfigTests;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convenience test suite for integration tests that verify support for
|
||||||
|
* {@link ApplicationContextInitializer ApplicationContextInitializers} (ACIs)
|
||||||
|
* in the TestContext framework.
|
||||||
|
*
|
||||||
|
* @author Sam Brannen
|
||||||
|
* @since 3.2
|
||||||
|
*/
|
||||||
|
@RunWith(Suite.class)
|
||||||
|
// Note: the following 'multi-line' layout is for enhanced code readability.
|
||||||
|
@SuiteClasses({//
|
||||||
|
MultipleInitializersXmlConfigTests.class,//
|
||||||
|
SingleInitializerAnnotationConfigTests.class,//
|
||||||
|
MultipleInitializersAnnotationConfigTests.class,//
|
||||||
|
MergedInitializersAnnotationConfigTests.class,//
|
||||||
|
OverriddenInitializersAnnotationConfigTests.class,//
|
||||||
|
OrderedInitializersAnnotationConfigTests.class,//
|
||||||
|
InitializerWithoutConfigFilesOrClassesTest.class //
|
||||||
|
})
|
||||||
|
public class AciTestSuite {
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2002-2012 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.test.context.junit4.aci;
|
||||||
|
|
||||||
|
import org.springframework.context.ApplicationContextInitializer;
|
||||||
|
import org.springframework.context.support.GenericApplicationContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Sam Brannen
|
||||||
|
* @since 3.2
|
||||||
|
*/
|
||||||
|
public class DevProfileInitializer implements ApplicationContextInitializer<GenericApplicationContext> {
|
||||||
|
|
||||||
|
public void initialize(GenericApplicationContext applicationContext) {
|
||||||
|
applicationContext.getEnvironment().setActiveProfiles("dev");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2002-2012 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.test.context.junit4.aci;
|
||||||
|
|
||||||
|
import org.springframework.context.ApplicationContextInitializer;
|
||||||
|
import org.springframework.context.support.GenericApplicationContext;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Sam Brannen
|
||||||
|
* @since 3.2
|
||||||
|
*/
|
||||||
|
public class FooBarAliasInitializer implements ApplicationContextInitializer<GenericApplicationContext> {
|
||||||
|
|
||||||
|
public void initialize(GenericApplicationContext applicationContext) {
|
||||||
|
applicationContext.registerAlias("foo", "bar");
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2002-2012 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.test.context.junit4.aci.annotation;
|
||||||
|
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.context.annotation.Profile;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Sam Brannen
|
||||||
|
* @since 3.2
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
@Profile("dev")
|
||||||
|
class DevProfileConfig {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public String baz() {
|
||||||
|
return "dev profile config";
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,38 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2002-2012 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.test.context.junit4.aci.annotation;
|
||||||
|
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Sam Brannen
|
||||||
|
* @since 3.2
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
class GlobalConfig {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public String foo() {
|
||||||
|
return "foo";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public String baz() {
|
||||||
|
return "global config";
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,61 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2002-2012 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.test.context.junit4.aci.annotation;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.ApplicationContextInitializer;
|
||||||
|
import org.springframework.context.annotation.AnnotatedBeanDefinitionReader;
|
||||||
|
import org.springframework.context.support.GenericApplicationContext;
|
||||||
|
import org.springframework.test.context.ContextConfiguration;
|
||||||
|
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||||
|
import org.springframework.test.context.junit4.aci.annotation.InitializerWithoutConfigFilesOrClassesTest.EntireAppInitializer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Integration test that verifies support for {@link ApplicationContextInitializer
|
||||||
|
* ApplicationContextInitializers} in the TestContext framework when the test
|
||||||
|
* class declares neither XML configuration files nor annotated configuration classes.
|
||||||
|
*
|
||||||
|
* @author Sam Brannen
|
||||||
|
* @since 3.2
|
||||||
|
*/
|
||||||
|
@RunWith(SpringJUnit4ClassRunner.class)
|
||||||
|
@ContextConfiguration(initializers = EntireAppInitializer.class)
|
||||||
|
public class InitializerWithoutConfigFilesOrClassesTest {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private String foo;
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void foo() {
|
||||||
|
assertEquals("foo", foo);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static class EntireAppInitializer implements ApplicationContextInitializer<GenericApplicationContext> {
|
||||||
|
|
||||||
|
public void initialize(GenericApplicationContext applicationContext) {
|
||||||
|
new AnnotatedBeanDefinitionReader(applicationContext).register(GlobalConfig.class);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,43 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2002-2012 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.test.context.junit4.aci.annotation;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.springframework.context.ApplicationContextInitializer;
|
||||||
|
import org.springframework.test.context.ContextConfiguration;
|
||||||
|
import org.springframework.test.context.junit4.aci.DevProfileInitializer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Integration tests that verify support for {@link ApplicationContextInitializer
|
||||||
|
* ApplicationContextInitializers} in conjunction with annotation-driven
|
||||||
|
* configuration in the TestContext framework.
|
||||||
|
*
|
||||||
|
* @author Sam Brannen
|
||||||
|
* @since 3.2
|
||||||
|
*/
|
||||||
|
@ContextConfiguration(initializers = DevProfileInitializer.class)
|
||||||
|
public class MergedInitializersAnnotationConfigTests extends SingleInitializerAnnotationConfigTests {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void activeBeans() {
|
||||||
|
assertEquals("foo", foo);
|
||||||
|
assertEquals("foo", bar);
|
||||||
|
assertEquals("dev profile config", baz);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2002-2012 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.test.context.junit4.aci.annotation;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.ApplicationContextInitializer;
|
||||||
|
import org.springframework.test.context.ContextConfiguration;
|
||||||
|
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||||
|
import org.springframework.test.context.junit4.aci.DevProfileInitializer;
|
||||||
|
import org.springframework.test.context.junit4.aci.FooBarAliasInitializer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Integration tests that verify support for {@link ApplicationContextInitializer
|
||||||
|
* ApplicationContextInitializers} in conjunction with annotation-driven
|
||||||
|
* configuration in the TestContext framework.
|
||||||
|
*
|
||||||
|
* @author Sam Brannen
|
||||||
|
* @since 3.2
|
||||||
|
*/
|
||||||
|
@RunWith(SpringJUnit4ClassRunner.class)
|
||||||
|
@ContextConfiguration(classes = { GlobalConfig.class, DevProfileConfig.class }, initializers = {
|
||||||
|
FooBarAliasInitializer.class, DevProfileInitializer.class })
|
||||||
|
public class MultipleInitializersAnnotationConfigTests {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private String foo, bar, baz;
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void activeBeans() {
|
||||||
|
assertEquals("foo", foo);
|
||||||
|
assertEquals("foo", bar);
|
||||||
|
assertEquals("dev profile config", baz);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,145 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2002-2012 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.test.context.junit4.aci.annotation;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.ApplicationContextInitializer;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.context.annotation.Profile;
|
||||||
|
import org.springframework.context.support.GenericApplicationContext;
|
||||||
|
import org.springframework.core.Ordered;
|
||||||
|
import org.springframework.core.annotation.Order;
|
||||||
|
import org.springframework.test.context.ContextConfiguration;
|
||||||
|
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||||
|
import org.springframework.test.context.junit4.aci.annotation.OrderedInitializersAnnotationConfigTests.ConfigTwo;
|
||||||
|
import org.springframework.test.context.junit4.aci.annotation.OrderedInitializersAnnotationConfigTests.ConfigOne;
|
||||||
|
import org.springframework.test.context.junit4.aci.annotation.OrderedInitializersAnnotationConfigTests.GlobalConfig;
|
||||||
|
import org.springframework.test.context.junit4.aci.annotation.OrderedInitializersAnnotationConfigTests.OrderedOneInitializer;
|
||||||
|
import org.springframework.test.context.junit4.aci.annotation.OrderedInitializersAnnotationConfigTests.OrderedTwoInitializer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Integration tests that verify that any {@link ApplicationContextInitializer
|
||||||
|
* ApplicationContextInitializers} implementing
|
||||||
|
* {@link org.springframework.core.Ordered Ordered} or marked with
|
||||||
|
* {@link org.springframework.core.annotation.Order @Order} will be sorted
|
||||||
|
* appropriately in conjunction with annotation-driven configuration in the
|
||||||
|
* TestContext framework.
|
||||||
|
*
|
||||||
|
* @author Sam Brannen
|
||||||
|
* @since 3.2
|
||||||
|
*/
|
||||||
|
@RunWith(SpringJUnit4ClassRunner.class)
|
||||||
|
// Note: the ordering of the config classes is intentionally: global, two, one.
|
||||||
|
// Note: the ordering of the initializers is intentionally: two, one.
|
||||||
|
@ContextConfiguration(classes = { GlobalConfig.class, ConfigTwo.class, ConfigOne.class }, initializers = {
|
||||||
|
OrderedTwoInitializer.class, OrderedOneInitializer.class })
|
||||||
|
public class OrderedInitializersAnnotationConfigTests {
|
||||||
|
|
||||||
|
private static final String PROFILE_GLOBAL = "global";
|
||||||
|
private static final String PROFILE_ONE = "one";
|
||||||
|
private static final String PROFILE_TWO = "two";
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private String foo, bar, baz;
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void activeBeans() {
|
||||||
|
assertEquals(PROFILE_GLOBAL, foo);
|
||||||
|
assertEquals(PROFILE_GLOBAL, bar);
|
||||||
|
assertEquals(PROFILE_TWO, baz);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
static class GlobalConfig {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public String foo() {
|
||||||
|
return PROFILE_GLOBAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public String bar() {
|
||||||
|
return PROFILE_GLOBAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public String baz() {
|
||||||
|
return PROFILE_GLOBAL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@Profile(PROFILE_ONE)
|
||||||
|
static class ConfigOne {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public String foo() {
|
||||||
|
return PROFILE_ONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public String bar() {
|
||||||
|
return PROFILE_ONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public String baz() {
|
||||||
|
return PROFILE_ONE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Configuration
|
||||||
|
@Profile(PROFILE_TWO)
|
||||||
|
static class ConfigTwo {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public String baz() {
|
||||||
|
return PROFILE_TWO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------------
|
||||||
|
|
||||||
|
static class OrderedOneInitializer implements ApplicationContextInitializer<GenericApplicationContext>, Ordered {
|
||||||
|
|
||||||
|
public void initialize(GenericApplicationContext applicationContext) {
|
||||||
|
applicationContext.getEnvironment().setActiveProfiles(PROFILE_ONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getOrder() {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Order(2)
|
||||||
|
static class OrderedTwoInitializer implements ApplicationContextInitializer<GenericApplicationContext> {
|
||||||
|
|
||||||
|
public void initialize(GenericApplicationContext applicationContext) {
|
||||||
|
applicationContext.getEnvironment().setActiveProfiles(PROFILE_TWO);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2002-2012 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.test.context.junit4.aci.annotation;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.springframework.context.ApplicationContextInitializer;
|
||||||
|
import org.springframework.test.context.ContextConfiguration;
|
||||||
|
import org.springframework.test.context.junit4.aci.DevProfileInitializer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Integration tests that verify support for {@link ApplicationContextInitializer
|
||||||
|
* ApplicationContextInitializers} in conjunction with annotation-driven
|
||||||
|
* configuration in the TestContext framework.
|
||||||
|
*
|
||||||
|
* @author Sam Brannen
|
||||||
|
* @since 3.2
|
||||||
|
*/
|
||||||
|
@ContextConfiguration(initializers = DevProfileInitializer.class, inheritInitializers = false)
|
||||||
|
public class OverriddenInitializersAnnotationConfigTests extends SingleInitializerAnnotationConfigTests {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Override
|
||||||
|
public void activeBeans() {
|
||||||
|
assertEquals("foo", foo);
|
||||||
|
assertNull(bar);
|
||||||
|
assertEquals("dev profile config", baz);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,60 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2002-2012 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.test.context.junit4.aci.annotation;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.annotation.Qualifier;
|
||||||
|
import org.springframework.context.ApplicationContextInitializer;
|
||||||
|
import org.springframework.test.context.ContextConfiguration;
|
||||||
|
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||||
|
import org.springframework.test.context.junit4.aci.FooBarAliasInitializer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Integration tests that verify support for {@link ApplicationContextInitializer
|
||||||
|
* ApplicationContextInitializers} in conjunction with annotation-driven
|
||||||
|
* configuration in the TestContext framework.
|
||||||
|
*
|
||||||
|
* @author Sam Brannen
|
||||||
|
* @since 3.2
|
||||||
|
*/
|
||||||
|
@RunWith(SpringJUnit4ClassRunner.class)
|
||||||
|
@ContextConfiguration(classes = { GlobalConfig.class, DevProfileConfig.class }, initializers = FooBarAliasInitializer.class)
|
||||||
|
public class SingleInitializerAnnotationConfigTests {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
protected String foo;
|
||||||
|
|
||||||
|
@Autowired(required = false)
|
||||||
|
@Qualifier("bar")
|
||||||
|
protected String bar;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
protected String baz;
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void activeBeans() {
|
||||||
|
assertEquals("foo", foo);
|
||||||
|
assertEquals("foo", bar);
|
||||||
|
assertEquals("global config", baz);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||||
|
|
||||||
|
<bean id="foo" class="java.lang.String">
|
||||||
|
<constructor-arg value="foo" />
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<bean id="baz" class="java.lang.String">
|
||||||
|
<constructor-arg value="global config" />
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<beans profile="dev">
|
||||||
|
<bean id="baz" class="java.lang.String">
|
||||||
|
<constructor-arg value="dev profile config" />
|
||||||
|
</bean>
|
||||||
|
</beans>
|
||||||
|
|
||||||
|
</beans>
|
|
@ -0,0 +1,53 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2002-2012 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.test.context.junit4.aci.xml;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.ApplicationContextInitializer;
|
||||||
|
import org.springframework.test.context.ContextConfiguration;
|
||||||
|
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||||
|
import org.springframework.test.context.junit4.aci.DevProfileInitializer;
|
||||||
|
import org.springframework.test.context.junit4.aci.FooBarAliasInitializer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Integration tests that verify support for {@link ApplicationContextInitializer
|
||||||
|
* ApplicationContextInitializers} in conjunction with XML configuration files
|
||||||
|
* in the TestContext framework.
|
||||||
|
*
|
||||||
|
* @author Sam Brannen
|
||||||
|
* @since 3.2
|
||||||
|
*/
|
||||||
|
@RunWith(SpringJUnit4ClassRunner.class)
|
||||||
|
@ContextConfiguration(initializers = { FooBarAliasInitializer.class, DevProfileInitializer.class })
|
||||||
|
public class MultipleInitializersXmlConfigTests {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private String foo, bar, baz;
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void activeBeans() {
|
||||||
|
assertEquals("foo", foo);
|
||||||
|
assertEquals("foo", bar);
|
||||||
|
assertEquals("dev profile config", baz);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -59,8 +59,8 @@
|
||||||
linkend="new-in-3.1-property-source-abstraction" />).
|
linkend="new-in-3.1-property-source-abstraction" />).
|
||||||
<classname>MockEnvironment</classname> and
|
<classname>MockEnvironment</classname> and
|
||||||
<classname>MockPropertySource</classname> are useful for developing
|
<classname>MockPropertySource</classname> are useful for developing
|
||||||
<emphasis>out-of-container</emphasis> unit tests for code that depends
|
<emphasis>out-of-container</emphasis> tests for code that depends on
|
||||||
on environment-specific properties.</para>
|
environment-specific properties.</para>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section xml:id="mock-objects-jndi">
|
<section xml:id="mock-objects-jndi">
|
||||||
|
@ -271,20 +271,20 @@
|
||||||
container take time to instantiate. For example, a project with 50 to
|
container take time to instantiate. For example, a project with 50 to
|
||||||
100 Hibernate mapping files might take 10 to 20 seconds to load the
|
100 Hibernate mapping files might take 10 to 20 seconds to load the
|
||||||
mapping files, and incurring that cost before running every test in
|
mapping files, and incurring that cost before running every test in
|
||||||
every test fixture leads to slower overall test runs that could reduce
|
every test fixture leads to slower overall test runs that reduce
|
||||||
productivity.</para>
|
developer productivity.</para>
|
||||||
|
|
||||||
<para>Test classes can provide either an array of <emphasis>resource
|
<para>Test classes typically declare either an array of
|
||||||
locations</emphasis> for XML configuration metadata — typically in the
|
<emphasis>resource locations</emphasis> for XML configuration metadata
|
||||||
classpath — or an array of <emphasis>annotated classes</emphasis> that
|
— often in the classpath — or an array of <emphasis>annotated
|
||||||
is used to configure the application. These locations or classes are
|
classes</emphasis> that is used to configure the application. These
|
||||||
the same as or similar to those specified in
|
locations or classes are the same as or similar to those specified in
|
||||||
<literal>web.xml</literal> or other deployment configuration
|
<literal>web.xml</literal> or other deployment configuration
|
||||||
files.</para>
|
files.</para>
|
||||||
|
|
||||||
<para>By default, once loaded, the configured
|
<para>By default, once loaded, the configured
|
||||||
<interfacename>ApplicationContext</interfacename> is reused for each
|
<interfacename>ApplicationContext</interfacename> is reused for each
|
||||||
test. Thus the setup cost is incurred only once (per test suite), and
|
test. Thus the setup cost is incurred only once per test suite, and
|
||||||
subsequent test execution is much faster. In this context, the term
|
subsequent test execution is much faster. In this context, the term
|
||||||
<emphasis>test suite</emphasis> means all tests run in the same JVM —
|
<emphasis>test suite</emphasis> means all tests run in the same JVM —
|
||||||
for example, all tests run from an Ant, Maven, or Gradle build for a
|
for example, all tests run from an Ant, Maven, or Gradle build for a
|
||||||
|
@ -311,11 +311,10 @@
|
||||||
contexts across various testing scenarios (e.g., for configuring
|
contexts across various testing scenarios (e.g., for configuring
|
||||||
Spring-managed object graphs, transactional proxies,
|
Spring-managed object graphs, transactional proxies,
|
||||||
<classname>DataSource</classname>s, etc.), thus avoiding the need to
|
<classname>DataSource</classname>s, etc.), thus avoiding the need to
|
||||||
duplicate complex test fixture set up for individual test
|
duplicate complex test fixture setup for individual test cases.</para>
|
||||||
cases.</para>
|
|
||||||
|
|
||||||
<para>As an example, consider the scenario where we have a class,
|
<para>As an example, consider the scenario where we have a class,
|
||||||
<classname>HibernateTitleRepository</classname>, that performs data
|
<classname>HibernateTitleRepository</classname>, that implements data
|
||||||
access logic for a <classname>Title</classname> domain entity. We want
|
access logic for a <classname>Title</classname> domain entity. We want
|
||||||
to write integration tests that test the following areas:</para>
|
to write integration tests that test the following areas:</para>
|
||||||
|
|
||||||
|
@ -348,7 +347,7 @@
|
||||||
<title>Transaction management</title>
|
<title>Transaction management</title>
|
||||||
|
|
||||||
<para>One common issue in tests that access a real database is their
|
<para>One common issue in tests that access a real database is their
|
||||||
affect on the state of the persistence store. Even when you're using a
|
effect on the state of the persistence store. Even when you're using a
|
||||||
development database, changes to the state may affect future tests.
|
development database, changes to the state may affect future tests.
|
||||||
Also, many operations — such as inserting or modifying persistent data
|
Also, many operations — such as inserting or modifying persistent data
|
||||||
— cannot be performed (or verified) outside a transaction.</para>
|
— cannot be performed (or verified) outside a transaction.</para>
|
||||||
|
@ -358,11 +357,11 @@
|
||||||
simply write code that can assume the existence of a transaction. If
|
simply write code that can assume the existence of a transaction. If
|
||||||
you call transactionally proxied objects in your tests, they will
|
you call transactionally proxied objects in your tests, they will
|
||||||
behave correctly, according to their configured transactional
|
behave correctly, according to their configured transactional
|
||||||
semantics. In addition, if test methods delete the contents of
|
semantics. In addition, if a test method deletes the contents of
|
||||||
selected tables while running within a transaction, the transaction
|
selected tables while running within the transaction managed for the
|
||||||
will roll back by default, and the database will return to its state
|
test, the transaction will roll back by default, and the database will
|
||||||
prior to execution of the test. Transactional support is provided to
|
return to its state prior to execution of the test. Transactional
|
||||||
your test class via a
|
support is provided to a test via a
|
||||||
<classname>PlatformTransactionManager</classname> bean defined in the
|
<classname>PlatformTransactionManager</classname> bean defined in the
|
||||||
test's application context.</para>
|
test's application context.</para>
|
||||||
|
|
||||||
|
@ -370,10 +369,10 @@
|
||||||
useful when you want a particular test to populate or modify the
|
useful when you want a particular test to populate or modify the
|
||||||
database — the TestContext framework can be instructed to cause the
|
database — the TestContext framework can be instructed to cause the
|
||||||
transaction to commit instead of roll back via the <link
|
transaction to commit instead of roll back via the <link
|
||||||
linkend="integration-testing-annotations">
|
linkend="integration-testing-annotations"><interfacename>@TransactionConfiguration</interfacename></link>
|
||||||
<interfacename>@TransactionConfiguration</interfacename> </link> and
|
and <link
|
||||||
<link linkend="integration-testing-annotations">
|
linkend="integration-testing-annotations"><interfacename>@Rollback</interfacename></link>
|
||||||
<interfacename>@Rollback</interfacename> </link> annotations.</para>
|
annotations.</para>
|
||||||
|
|
||||||
<para>See transaction management with the <link
|
<para>See transaction management with the <link
|
||||||
linkend="testcontext-tx">TestContext framework</link>.</para>
|
linkend="testcontext-tx">TestContext framework</link>.</para>
|
||||||
|
@ -396,8 +395,8 @@
|
||||||
</listitem>
|
</listitem>
|
||||||
|
|
||||||
<listitem>
|
<listitem>
|
||||||
<para>A <classname>JdbcTemplate</classname>, for executing
|
<para>A <classname>JdbcTemplate</classname>, for executing SQL
|
||||||
SQL statements to query the database. Such queries can be used to
|
statements to query the database. Such queries can be used to
|
||||||
confirm database state both <emphasis>prior to</emphasis> and
|
confirm database state both <emphasis>prior to</emphasis> and
|
||||||
<emphasis>after</emphasis> execution of database-related
|
<emphasis>after</emphasis> execution of database-related
|
||||||
application code, and Spring ensures that such queries run in the
|
application code, and Spring ensures that such queries run in the
|
||||||
|
@ -422,14 +421,13 @@
|
||||||
<title>JDBC Testing Support</title>
|
<title>JDBC Testing Support</title>
|
||||||
|
|
||||||
<para>The <literal>org.springframework.test.jdbc</literal> package
|
<para>The <literal>org.springframework.test.jdbc</literal> package
|
||||||
contains <classname>JdbcTestUtils</classname>, which is a
|
contains <classname>JdbcTestUtils</classname>, which is a collection of
|
||||||
collection of JDBC related utility functions intended to simplify
|
JDBC related utility functions intended to simplify standard database
|
||||||
standard database testing scenarios. <emphasis>Note that <link
|
testing scenarios. <emphasis>Note that <link
|
||||||
linkend="testcontext-support-classes-junit4">
|
linkend="testcontext-support-classes-junit4"><classname>AbstractTransactionalJUnit4SpringContextTests</classname></link>
|
||||||
<classname>AbstractTransactionalJUnit4SpringContextTests</classname>
|
and <link
|
||||||
</link> and <link linkend="testcontext-support-classes-testng">
|
linkend="testcontext-support-classes-testng"><classname>AbstractTransactionalTestNGSpringContextTests</classname></link>
|
||||||
<classname>AbstractTransactionalTestNGSpringContextTests</classname>
|
provide convenience methods which delegate to
|
||||||
</link> provide convenience methods which delegate to
|
|
||||||
<classname>JdbcTestUtils</classname> internally.</emphasis></para>
|
<classname>JdbcTestUtils</classname> internally.</emphasis></para>
|
||||||
|
|
||||||
<para>The <literal>spring-jdbc</literal> module provides support for
|
<para>The <literal>spring-jdbc</literal> module provides support for
|
||||||
|
@ -460,8 +458,8 @@
|
||||||
|
|
||||||
<para>Defines class-level metadata that is used to determine how
|
<para>Defines class-level metadata that is used to determine how
|
||||||
to load and configure an
|
to load and configure an
|
||||||
<interfacename>ApplicationContext</interfacename> for test
|
<interfacename>ApplicationContext</interfacename> for integration
|
||||||
classes. Specifically,
|
tests. Specifically,
|
||||||
<interfacename>@ContextConfiguration</interfacename> declares
|
<interfacename>@ContextConfiguration</interfacename> declares
|
||||||
<emphasis>either</emphasis> the application context resource
|
<emphasis>either</emphasis> the application context resource
|
||||||
<varname>locations</varname> <emphasis>or</emphasis> the annotated
|
<varname>locations</varname> <emphasis>or</emphasis> the annotated
|
||||||
|
@ -471,8 +469,8 @@
|
||||||
<para>Resource locations are typically XML configuration files
|
<para>Resource locations are typically XML configuration files
|
||||||
located in the classpath; whereas, annotated classes are typically
|
located in the classpath; whereas, annotated classes are typically
|
||||||
<interfacename>@Configuration</interfacename> classes. However,
|
<interfacename>@Configuration</interfacename> classes. However,
|
||||||
resource locations could also refer to files in the file system,
|
resource locations can also refer to files in the file system, and
|
||||||
and annotated classes could be component classes, etc.</para>
|
annotated classes can be component classes, etc.</para>
|
||||||
|
|
||||||
<programlisting language="java"><emphasis role="bold">@ContextConfiguration</emphasis>("/test-config.xml")
|
<programlisting language="java"><emphasis role="bold">@ContextConfiguration</emphasis>("/test-config.xml")
|
||||||
public class XmlApplicationContextTests {
|
public class XmlApplicationContextTests {
|
||||||
|
@ -485,13 +483,27 @@ public class ConfigClassApplicationContextTests {
|
||||||
<lineannotation>// class body...</lineannotation>
|
<lineannotation>// class body...</lineannotation>
|
||||||
}</programlisting>
|
}</programlisting>
|
||||||
|
|
||||||
|
<para>As an alternative or in addition to declaring resource
|
||||||
|
locations or annotated classes,
|
||||||
|
<interfacename>@ContextConfiguration</interfacename> may be used
|
||||||
|
to declare
|
||||||
|
<interfacename>ApplicationContextInitializer</interfacename>
|
||||||
|
classes.</para>
|
||||||
|
|
||||||
|
<programlisting language="java"><emphasis role="bold">@ContextConfiguration</emphasis>(<emphasis
|
||||||
|
role="bold">initializers</emphasis>=CustomContextIntializer.class)
|
||||||
|
public class ContextInitializerTests {
|
||||||
|
<lineannotation>// class body...</lineannotation>
|
||||||
|
}</programlisting>
|
||||||
|
|
||||||
<para><interfacename>@ContextConfiguration</interfacename> may
|
<para><interfacename>@ContextConfiguration</interfacename> may
|
||||||
optionally be used to declare the
|
optionally be used to declare the
|
||||||
<interfacename>ContextLoader</interfacename> strategy as well.
|
<interfacename>ContextLoader</interfacename> strategy as well.
|
||||||
Note, however, that you typically do not need to explicitly
|
Note, however, that you typically do not need to explicitly
|
||||||
configure the loader since the default loader supports either
|
configure the loader since the default loader supports either
|
||||||
resource <varname>locations</varname> or annotated
|
resource <varname>locations</varname> or annotated
|
||||||
<varname>classes</varname>.</para>
|
<varname>classes</varname> as well as
|
||||||
|
<varname>initializers</varname>.</para>
|
||||||
|
|
||||||
<programlisting language="java"><emphasis role="bold">@ContextConfiguration</emphasis>(<emphasis
|
<programlisting language="java"><emphasis role="bold">@ContextConfiguration</emphasis>(<emphasis
|
||||||
role="bold">locations</emphasis>="/test-context.xml", <emphasis
|
role="bold">locations</emphasis>="/test-context.xml", <emphasis
|
||||||
|
@ -503,8 +515,8 @@ public class CustomLoaderXmlApplicationContextTests {
|
||||||
<note>
|
<note>
|
||||||
<para><interfacename>@ContextConfiguration</interfacename>
|
<para><interfacename>@ContextConfiguration</interfacename>
|
||||||
provides support for <emphasis>inheriting</emphasis> resource
|
provides support for <emphasis>inheriting</emphasis> resource
|
||||||
locations or configuration classes declared by superclasses by
|
locations or configuration classes as well as context
|
||||||
default.</para>
|
initializers declared by superclasses by default.</para>
|
||||||
</note>
|
</note>
|
||||||
|
|
||||||
<para>See <link linkend="testcontext-ctx-management">Context
|
<para>See <link linkend="testcontext-ctx-management">Context
|
||||||
|
@ -650,8 +662,8 @@ public class CustomTestExecutionListenerTests {
|
||||||
should be used to drive transactions can be explicitly specified
|
should be used to drive transactions can be explicitly specified
|
||||||
if there are multiple beans of type
|
if there are multiple beans of type
|
||||||
<interfacename>PlatformTransactionManager</interfacename> in the
|
<interfacename>PlatformTransactionManager</interfacename> in the
|
||||||
test's <interfacename>ApplicationContext</interfacename> and the
|
test's <interfacename>ApplicationContext</interfacename> and if
|
||||||
bean name of the desired
|
the bean name of the desired
|
||||||
<interfacename>PlatformTransactionManager</interfacename> is not
|
<interfacename>PlatformTransactionManager</interfacename> is not
|
||||||
"transactionManager". In addition, you can change the
|
"transactionManager". In addition, you can change the
|
||||||
<literal>defaultRollback</literal> flag to
|
<literal>defaultRollback</literal> flag to
|
||||||
|
@ -1227,15 +1239,21 @@ public class MyTest {
|
||||||
application context resource <literal>locations</literal> or annotated
|
application context resource <literal>locations</literal> or annotated
|
||||||
<varname>classes</varname>, the configured
|
<varname>classes</varname>, the configured
|
||||||
<interfacename>ContextLoader</interfacename> determines how to load a
|
<interfacename>ContextLoader</interfacename> determines how to load a
|
||||||
context from a default location or default configuration
|
context from a default location or default configuration classes. In
|
||||||
classes.</para>
|
addition to context resource <varname>locations</varname> and
|
||||||
|
annotated <varname>classes</varname>, an application context can also
|
||||||
|
be configured via application context
|
||||||
|
<varname>initializers</varname>.</para>
|
||||||
|
|
||||||
<para>The following sections explain how to configure an
|
<para>The following sections explain how to configure an
|
||||||
<interfacename>ApplicationContext</interfacename> via XML
|
<interfacename>ApplicationContext</interfacename> via XML
|
||||||
configuration files or annotated classes (typically
|
configuration files, annotated classes (typically
|
||||||
<interfacename>@Configuration</interfacename> classes) using Spring's
|
<interfacename>@Configuration</interfacename> classes), or context
|
||||||
<interfacename>@ContextConfiguration</interfacename>
|
initializers using Spring's
|
||||||
annotation.</para>
|
<interfacename>@ContextConfiguration</interfacename> annotation.
|
||||||
|
Alternatively, you can implement and configure your own custom
|
||||||
|
<interfacename>SmartContextLoader</interfacename> for advanced use
|
||||||
|
cases.</para>
|
||||||
|
|
||||||
<section xml:id="testcontext-ctx-management-xml">
|
<section xml:id="testcontext-ctx-management-xml">
|
||||||
<title>Context configuration with XML resources</title>
|
<title>Context configuration with XML resources</title>
|
||||||
|
@ -1245,18 +1263,16 @@ public class MyTest {
|
||||||
class with <interfacename>@ContextConfiguration</interfacename> and
|
class with <interfacename>@ContextConfiguration</interfacename> and
|
||||||
configure the <literal>locations</literal> attribute with an array
|
configure the <literal>locations</literal> attribute with an array
|
||||||
that contains the resource locations of XML configuration metadata.
|
that contains the resource locations of XML configuration metadata.
|
||||||
A plain path — for example <literal>"context.xml"</literal> — will
|
A plain or relative path — for example
|
||||||
be treated as a classpath resource that is relative to the package
|
<literal>"context.xml"</literal> — will be treated as a classpath
|
||||||
in which the test class is defined. A path starting with a slash is
|
resource that is relative to the package in which the test class is
|
||||||
treated as an absolute classpath location, for example
|
defined. A path starting with a slash is treated as an absolute
|
||||||
|
classpath location, for example
|
||||||
<literal>"/org/example/config.xml"</literal>. A path which
|
<literal>"/org/example/config.xml"</literal>. A path which
|
||||||
represents a resource URL (i.e., a path prefixed with
|
represents a resource URL (i.e., a path prefixed with
|
||||||
<literal>classpath:</literal>, <literal>file:</literal>,
|
<literal>classpath:</literal>, <literal>file:</literal>,
|
||||||
<literal>http:</literal>, etc.) will be used <emphasis>as
|
<literal>http:</literal>, etc.) will be used <emphasis>as
|
||||||
is</emphasis>. Alternatively, you can implement and configure your
|
is</emphasis>.</para>
|
||||||
own custom <interfacename>ContextLoader</interfacename> or
|
|
||||||
<interfacename>SmartContextLoader</interfacename> for advanced use
|
|
||||||
cases.</para>
|
|
||||||
|
|
||||||
<programlisting language="java">@RunWith(SpringJUnit4ClassRunner.class)
|
<programlisting language="java">@RunWith(SpringJUnit4ClassRunner.class)
|
||||||
<lineannotation>// ApplicationContext will be loaded from "/app-config.xml" and
|
<lineannotation>// ApplicationContext will be loaded from "/app-config.xml" and
|
||||||
|
@ -1269,10 +1285,10 @@ public class MyTest {
|
||||||
<para><interfacename>@ContextConfiguration</interfacename> supports
|
<para><interfacename>@ContextConfiguration</interfacename> supports
|
||||||
an alias for the <literal>locations</literal> attribute through the
|
an alias for the <literal>locations</literal> attribute through the
|
||||||
standard Java <literal>value</literal> attribute. Thus, if you do
|
standard Java <literal>value</literal> attribute. Thus, if you do
|
||||||
not need to configure a custom
|
not need to declare additional attributes in
|
||||||
<interfacename>ContextLoader</interfacename>, you can omit the
|
<interfacename>@ContextConfiguration</interfacename>, you can omit
|
||||||
declaration of the <literal>locations</literal> attribute name and
|
the declaration of the <literal>locations</literal> attribute name
|
||||||
declare the resource locations by using the shorthand format
|
and declare the resource locations by using the shorthand format
|
||||||
demonstrated in the following example.</para>
|
demonstrated in the following example.</para>
|
||||||
|
|
||||||
<programlisting language="java">@RunWith(SpringJUnit4ClassRunner.class)
|
<programlisting language="java">@RunWith(SpringJUnit4ClassRunner.class)
|
||||||
|
@ -1296,7 +1312,8 @@ public class MyTest {
|
||||||
<programlisting language="java">package com.example;
|
<programlisting language="java">package com.example;
|
||||||
|
|
||||||
@RunWith(SpringJUnit4ClassRunner.class)
|
@RunWith(SpringJUnit4ClassRunner.class)
|
||||||
<lineannotation>// ApplicationContext will be loaded from "classpath:/com/example/MyTest-context.xml"</lineannotation>
|
<lineannotation>// ApplicationContext will be loaded from
|
||||||
|
// "classpath:/com/example/MyTest-context.xml"</lineannotation>
|
||||||
<emphasis role="bold">@ContextConfiguration</emphasis>
|
<emphasis role="bold">@ContextConfiguration</emphasis>
|
||||||
public class MyTest {
|
public class MyTest {
|
||||||
<lineannotation>// class body...</lineannotation>
|
<lineannotation>// class body...</lineannotation>
|
||||||
|
@ -1311,15 +1328,11 @@ public class MyTest {
|
||||||
<xref linkend="beans-java" />), annotate your test class with
|
<xref linkend="beans-java" />), annotate your test class with
|
||||||
<interfacename>@ContextConfiguration</interfacename> and configure
|
<interfacename>@ContextConfiguration</interfacename> and configure
|
||||||
the <literal>classes</literal> attribute with an array that contains
|
the <literal>classes</literal> attribute with an array that contains
|
||||||
references to annotated classes. Alternatively, you can implement
|
references to annotated classes.</para>
|
||||||
and configure your own custom
|
|
||||||
<interfacename>ContextLoader</interfacename> or
|
|
||||||
<interfacename>SmartContextLoader</interfacename> for advanced use
|
|
||||||
cases.</para>
|
|
||||||
|
|
||||||
<programlisting language="java">@RunWith(SpringJUnit4ClassRunner.class)
|
<programlisting language="java">@RunWith(SpringJUnit4ClassRunner.class)
|
||||||
<lineannotation>// ApplicationContext will be loaded from AppConfig and TestConfig</lineannotation>
|
<lineannotation>// ApplicationContext will be loaded from AppConfig and TestConfig</lineannotation>
|
||||||
<emphasis role="bold">@ContextConfiguration(classes={AppConfig.class, TestConfig.class})</emphasis>
|
<emphasis role="bold">@ContextConfiguration(classes = {AppConfig.class, TestConfig.class})</emphasis>
|
||||||
public class MyTest {
|
public class MyTest {
|
||||||
<lineannotation>// class body...</lineannotation>
|
<lineannotation>// class body...</lineannotation>
|
||||||
}</programlisting>
|
}</programlisting>
|
||||||
|
@ -1340,10 +1353,9 @@ public class MyTest {
|
||||||
arbitrary. In addition, a test class can contain more than one
|
arbitrary. In addition, a test class can contain more than one
|
||||||
static inner configuration class if desired.</para>
|
static inner configuration class if desired.</para>
|
||||||
|
|
||||||
<programlisting language="java">package com.example;
|
<programlisting language="java">@RunWith(SpringJUnit4ClassRunner.class)
|
||||||
|
<lineannotation>// ApplicationContext will be loaded from the
|
||||||
@RunWith(SpringJUnit4ClassRunner.class)
|
// static inner Config class</lineannotation>
|
||||||
<lineannotation>// ApplicationContext will be loaded from the static inner Config class</lineannotation>
|
|
||||||
<emphasis role="bold">@ContextConfiguration</emphasis>
|
<emphasis role="bold">@ContextConfiguration</emphasis>
|
||||||
public class OrderServiceTest {
|
public class OrderServiceTest {
|
||||||
|
|
||||||
|
@ -1406,27 +1418,85 @@ public class OrderServiceTest {
|
||||||
other type of configuration.</para>
|
other type of configuration.</para>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
<section xml:id="testcontext-ctx-management-initializers">
|
||||||
|
<title>Context configuration with context initializers</title>
|
||||||
|
|
||||||
|
<para>To configure an
|
||||||
|
<interfacename>ApplicationContext</interfacename> for your tests
|
||||||
|
using context initializers, annotate your test class with
|
||||||
|
<interfacename>@ContextConfiguration</interfacename> and configure
|
||||||
|
the <literal>initializers</literal> attribute with an array that
|
||||||
|
contains references to classes that implement
|
||||||
|
<interfacename>ApplicationContextInitializer</interfacename>. The
|
||||||
|
declared context initializers will then be used to initialize the
|
||||||
|
<interfacename>ConfigurableApplicationContext</interfacename> that
|
||||||
|
is loaded for your tests. Note that the concrete
|
||||||
|
<interfacename>ConfigurableApplicationContext</interfacename> type
|
||||||
|
supported by each declared initializer must be compatible with the
|
||||||
|
type of <interfacename>ApplicationContext</interfacename> created by
|
||||||
|
the <interfacename>SmartContextLoader</interfacename> in use (i.e.,
|
||||||
|
typically a <classname>GenericApplicationContext</classname>).
|
||||||
|
Furthermore, the order in which the initializers are invoked depends
|
||||||
|
on whether they implement Spring's
|
||||||
|
<interfacename>Ordered</interfacename> interface or are annotated
|
||||||
|
with Spring's <interfacename>@Order</interfacename>
|
||||||
|
annotation.</para>
|
||||||
|
|
||||||
|
<programlisting language="java">@RunWith(SpringJUnit4ClassRunner.class)
|
||||||
|
<lineannotation>// ApplicationContext will be loaded from TestConfig
|
||||||
|
</lineannotation><lineannotation>// and initialized by TestAppCtxInitializer</lineannotation>
|
||||||
|
<emphasis role="bold">@ContextConfiguration(
|
||||||
|
classes = TestConfig.class,
|
||||||
|
initializers = TestAppCtxInitializer.class)</emphasis>
|
||||||
|
public class MyTest {
|
||||||
|
<lineannotation>// class body...</lineannotation>
|
||||||
|
}</programlisting>
|
||||||
|
|
||||||
|
<para>It is also possible to omit the declaration of XML
|
||||||
|
configuration files or annotated classes in
|
||||||
|
<interfacename>@ContextConfiguration</interfacename> entirely and
|
||||||
|
instead declare only
|
||||||
|
<interfacename>ApplicationContextInitializer</interfacename> classes
|
||||||
|
which are then responsible for registering beans in the context —
|
||||||
|
for example, by programmatically loading bean definitions from XML
|
||||||
|
files or configuration classes.</para>
|
||||||
|
|
||||||
|
<programlisting language="java">@RunWith(SpringJUnit4ClassRunner.class)
|
||||||
|
<lineannotation>// ApplicationContext will be initialized by EntireAppInitializer
|
||||||
|
</lineannotation><lineannotation>// which presumably registers beans in the context</lineannotation>
|
||||||
|
<emphasis role="bold">@ContextConfiguration(initializers = EntireAppInitializer.class)</emphasis>
|
||||||
|
public class MyTest {
|
||||||
|
<lineannotation>// class body...</lineannotation>
|
||||||
|
}</programlisting>
|
||||||
|
</section>
|
||||||
|
|
||||||
<section xml:id="testcontext-ctx-management-inheritance">
|
<section xml:id="testcontext-ctx-management-inheritance">
|
||||||
<title>Context configuration inheritance</title>
|
<title>Context configuration inheritance</title>
|
||||||
|
|
||||||
<para><interfacename>@ContextConfiguration</interfacename> supports
|
<para><interfacename>@ContextConfiguration</interfacename> supports
|
||||||
a boolean <literal>inheritLocations</literal> attribute that denotes
|
boolean <varname>inheritLocations</varname> and
|
||||||
whether resource locations or annotated classes declared by
|
<varname>inheritInitializers</varname> attributes that denote
|
||||||
superclasses should be <emphasis>inherited</emphasis>. The default
|
whether resource locations or annotated classes and context
|
||||||
value is <literal>true</literal>. This means that a test class
|
initializers declared by superclasses should be
|
||||||
inherits the resource locations or annotated classes declared by any
|
<emphasis>inherited</emphasis>. The default value for both flags is
|
||||||
superclasses. Specifically, the resource locations or annotated
|
<literal>true</literal>. This means that a test class inherits the
|
||||||
classes for a test class are appended to the list of resource
|
resource locations or annotated classes as well as the context
|
||||||
locations or annotated classes declared by superclasses. Thus,
|
initializers declared by any superclasses. Specifically, the
|
||||||
subclasses have the option of <emphasis>extending</emphasis> the
|
resource locations or annotated classes for a test class are
|
||||||
list of resource locations or annotated classes.</para>
|
appended to the list of resource locations or annotated classes
|
||||||
|
declared by superclasses. Similarly, the initializers for a given
|
||||||
|
test class will be added to the set of initializers defined by test
|
||||||
|
superclasses. Thus, subclasses have the option of
|
||||||
|
<emphasis>extending</emphasis> the resource locations, annotated
|
||||||
|
classes, or context initializers.</para>
|
||||||
|
|
||||||
<para>If <interfacename>@ContextConfiguration</interfacename>'s
|
<para>If <interfacename>@ContextConfiguration</interfacename>'s
|
||||||
<literal>inheritLocations</literal> attribute is set to
|
<literal>inheritLocations</literal> or
|
||||||
|
<varname>inheritInitializers</varname> attribute is set to
|
||||||
<literal>false</literal>, the resource locations or annotated
|
<literal>false</literal>, the resource locations or annotated
|
||||||
classes for the test class <emphasis>shadow</emphasis> and
|
classes and the context initializers, respectively, for the test
|
||||||
effectively replace any resource locations or annotated classes
|
class <emphasis>shadow</emphasis> and effectively replace the
|
||||||
defined by superclasses.</para>
|
configuration defined by superclasses.</para>
|
||||||
|
|
||||||
<para>In the following example that uses XML resource locations, the
|
<para>In the following example that uses XML resource locations, the
|
||||||
<interfacename>ApplicationContext</interfacename> for
|
<interfacename>ApplicationContext</interfacename> for
|
||||||
|
@ -1439,14 +1509,15 @@ public class OrderServiceTest {
|
||||||
<emphasis>"base-config.xml"</emphasis>.</para>
|
<emphasis>"base-config.xml"</emphasis>.</para>
|
||||||
|
|
||||||
<programlisting language="java">@RunWith(SpringJUnit4ClassRunner.class)
|
<programlisting language="java">@RunWith(SpringJUnit4ClassRunner.class)
|
||||||
<lineannotation>// ApplicationContext will be loaded from "/base-config.xml" in the root of the classpath</lineannotation>
|
<lineannotation>// ApplicationContext will be loaded from "/base-config.xml"
|
||||||
|
// in the root of the classpath</lineannotation>
|
||||||
<emphasis role="bold">@ContextConfiguration("/base-config.xml")</emphasis>
|
<emphasis role="bold">@ContextConfiguration("/base-config.xml")</emphasis>
|
||||||
public class BaseTest {
|
public class BaseTest {
|
||||||
<lineannotation>// class body...</lineannotation>
|
<lineannotation>// class body...</lineannotation>
|
||||||
}
|
}
|
||||||
|
|
||||||
<lineannotation>// ApplicationContext will be loaded from "/base-config.xml" and "/extended-config.xml"</lineannotation>
|
<lineannotation>// ApplicationContext will be loaded from "/base-config.xml" and
|
||||||
<lineannotation>// in the root of the classpath</lineannotation>
|
// "/extended-config.xml" </lineannotation><lineannotation>in the root of the classpath</lineannotation>
|
||||||
<emphasis role="bold">@ContextConfiguration("/extended-config.xml")</emphasis>
|
<emphasis role="bold">@ContextConfiguration("/extended-config.xml")</emphasis>
|
||||||
public class ExtendedTest extends BaseTest {
|
public class ExtendedTest extends BaseTest {
|
||||||
<lineannotation>// class body...</lineannotation>
|
<lineannotation>// class body...</lineannotation>
|
||||||
|
@ -1463,13 +1534,38 @@ public class ExtendedTest extends BaseTest {
|
||||||
|
|
||||||
<programlisting language="java">@RunWith(SpringJUnit4ClassRunner.class)
|
<programlisting language="java">@RunWith(SpringJUnit4ClassRunner.class)
|
||||||
<lineannotation>// ApplicationContext will be loaded from BaseConfig</lineannotation>
|
<lineannotation>// ApplicationContext will be loaded from BaseConfig</lineannotation>
|
||||||
<emphasis role="bold">@ContextConfiguration(classes=BaseConfig.class)</emphasis>
|
<emphasis role="bold">@ContextConfiguration(classes = BaseConfig.class)</emphasis>
|
||||||
public class BaseTest {
|
public class BaseTest {
|
||||||
<lineannotation>// class body...</lineannotation>
|
<lineannotation>// class body...</lineannotation>
|
||||||
}
|
}
|
||||||
|
|
||||||
<lineannotation>// ApplicationContext will be loaded from BaseConfig and ExtendedConfig</lineannotation>
|
<lineannotation>// ApplicationContext will be loaded from BaseConfig and ExtendedConfig</lineannotation>
|
||||||
<emphasis role="bold">@ContextConfiguration(classes=ExtendedConfig.class)</emphasis>
|
<emphasis role="bold">@ContextConfiguration(classes = ExtendedConfig.class)</emphasis>
|
||||||
|
public class ExtendedTest extends BaseTest {
|
||||||
|
<lineannotation>// class body...</lineannotation>
|
||||||
|
}</programlisting>
|
||||||
|
|
||||||
|
<para>In the following example that uses context initializers, the
|
||||||
|
<interfacename>ApplicationContext</interfacename> for
|
||||||
|
<classname>ExtendedTest</classname> will be initialized using
|
||||||
|
<classname>BaseInitializer</classname> <emphasis
|
||||||
|
role="bold">and</emphasis>
|
||||||
|
<classname>ExtendedInitializer</classname>. Note, however, that the
|
||||||
|
order in which the initializers are invoked depends on whether they
|
||||||
|
implement Spring's <interfacename>Ordered</interfacename> interface
|
||||||
|
or are annotated with Spring's <interfacename>@Order</interfacename>
|
||||||
|
annotation.</para>
|
||||||
|
|
||||||
|
<programlisting language="java">@RunWith(SpringJUnit4ClassRunner.class)
|
||||||
|
<lineannotation>// ApplicationContext will be initialized by BaseInitializer</lineannotation>
|
||||||
|
<emphasis role="bold">@ContextConfiguration(initializers=BaseInitializer.class)</emphasis>
|
||||||
|
public class BaseTest {
|
||||||
|
<lineannotation>// class body...</lineannotation>
|
||||||
|
}
|
||||||
|
|
||||||
|
<lineannotation>// ApplicationContext will be initialized by BaseInitializer
|
||||||
|
// and ExtendedInitializer</lineannotation>
|
||||||
|
<emphasis role="bold">@ContextConfiguration(initializers=ExtendedInitializer.class)</emphasis>
|
||||||
public class ExtendedTest extends BaseTest {
|
public class ExtendedTest extends BaseTest {
|
||||||
<lineannotation>// class body...</lineannotation>
|
<lineannotation>// class body...</lineannotation>
|
||||||
}</programlisting>
|
}</programlisting>
|
||||||
|
@ -1478,9 +1574,9 @@ public class ExtendedTest extends BaseTest {
|
||||||
<section xml:id="testcontext-ctx-management-env-profiles">
|
<section xml:id="testcontext-ctx-management-env-profiles">
|
||||||
<title>Context configuration with environment profiles</title>
|
<title>Context configuration with environment profiles</title>
|
||||||
|
|
||||||
<para>Spring 3.1 introduces first-class support in the framework for
|
<para>Spring 3.1 introduced first-class support in the framework for
|
||||||
the notion of environments and profiles (a.k.a., <emphasis>bean
|
the notion of environments and profiles (a.k.a., <emphasis>bean
|
||||||
definition profiles</emphasis>), and integration tests can now be
|
definition profiles</emphasis>), and integration tests can be
|
||||||
configured to activate particular bean definition profiles for
|
configured to activate particular bean definition profiles for
|
||||||
various testing scenarios. This is achieved by annotating a test
|
various testing scenarios. This is achieved by annotating a test
|
||||||
class with the <interfacename>@ActiveProfiles</interfacename>
|
class with the <interfacename>@ActiveProfiles</interfacename>
|
||||||
|
@ -1634,7 +1730,7 @@ public class TransferServiceConfig {
|
||||||
|
|
||||||
@RunWith(SpringJUnit4ClassRunner.class)
|
@RunWith(SpringJUnit4ClassRunner.class)
|
||||||
@ContextConfiguration(
|
@ContextConfiguration(
|
||||||
classes={
|
classes = {
|
||||||
TransferServiceConfig.class,
|
TransferServiceConfig.class,
|
||||||
StandaloneDataConfig.class,
|
StandaloneDataConfig.class,
|
||||||
JndiDataConfig.class})
|
JndiDataConfig.class})
|
||||||
|
@ -1715,6 +1811,11 @@ public class TransferServiceTest {
|
||||||
@ContextConfiguration)</emphasis></para>
|
@ContextConfiguration)</emphasis></para>
|
||||||
</listitem>
|
</listitem>
|
||||||
|
|
||||||
|
<listitem>
|
||||||
|
<para><varname>contextInitializerClasses</varname>
|
||||||
|
<emphasis>(from @ContextConfiguration)</emphasis></para>
|
||||||
|
</listitem>
|
||||||
|
|
||||||
<listitem>
|
<listitem>
|
||||||
<para><varname>contextLoader</varname> <emphasis>(from
|
<para><varname>contextLoader</varname> <emphasis>(from
|
||||||
@ContextConfiguration)</emphasis></para>
|
@ContextConfiguration)</emphasis></para>
|
||||||
|
@ -1737,8 +1838,8 @@ public class TransferServiceTest {
|
||||||
also defines <literal>{"app-config.xml",
|
also defines <literal>{"app-config.xml",
|
||||||
"test-config.xml"}</literal> for its locations (either explicitly or
|
"test-config.xml"}</literal> for its locations (either explicitly or
|
||||||
implicitly through inheritance) and does not define a different
|
implicitly through inheritance) and does not define a different
|
||||||
<interfacename>ContextLoader</interfacename> or different active
|
<interfacename>ContextLoader</interfacename>, different active
|
||||||
profiles, then the same
|
profiles, or different context initializers, then the same
|
||||||
<interfacename>ApplicationContext</interfacename> will be shared by
|
<interfacename>ApplicationContext</interfacename> will be shared by
|
||||||
both test classes. This means that the setup cost for loading an
|
both test classes. This means that the setup cost for loading an
|
||||||
application context is incurred only once (per test suite), and
|
application context is incurred only once (per test suite), and
|
||||||
|
@ -2103,7 +2204,7 @@ public void updateWithSessionFlush() {
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section xml:id="testcontext-support-classes">
|
<section xml:id="testcontext-support-classes">
|
||||||
<title>TestContext support classes</title>
|
<title>TestContext Framework support classes</title>
|
||||||
|
|
||||||
<section xml:id="testcontext-support-classes-junit4">
|
<section xml:id="testcontext-support-classes-junit4">
|
||||||
<title>JUnit support classes</title>
|
<title>JUnit support classes</title>
|
||||||
|
@ -2157,14 +2258,14 @@ public void updateWithSessionFlush() {
|
||||||
</listitem>
|
</listitem>
|
||||||
|
|
||||||
<listitem>
|
<listitem>
|
||||||
<para><literal>jdbcTemplate</literal>: Use this
|
<para><literal>jdbcTemplate</literal>: Use this variable to
|
||||||
variable to execute SQL statements to query the database.
|
execute SQL statements to query the database. Such queries
|
||||||
Such queries can be used to confirm database state both
|
can be used to confirm database state both <emphasis>prior
|
||||||
<emphasis>prior to</emphasis> and <emphasis>after</emphasis>
|
to</emphasis> and <emphasis>after</emphasis> execution of
|
||||||
execution of database-related application code, and Spring
|
database-related application code, and Spring ensures that
|
||||||
ensures that such queries run in the scope of the same
|
such queries run in the scope of the same transaction as the
|
||||||
transaction as the application code. When used in
|
application code. When used in conjunction with an ORM tool,
|
||||||
conjunction with an ORM tool, be sure to avoid <link
|
be sure to avoid <link
|
||||||
linkend="testcontext-tx-false-positives">false
|
linkend="testcontext-tx-false-positives">false
|
||||||
positives</link>.</para>
|
positives</link>.</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
|
@ -2266,14 +2367,14 @@ public class SimpleTest {
|
||||||
</listitem>
|
</listitem>
|
||||||
|
|
||||||
<listitem>
|
<listitem>
|
||||||
<para><literal>jdbcTemplate</literal>: Use this
|
<para><literal>jdbcTemplate</literal>: Use this variable to
|
||||||
variable to execute SQL statements to query the database.
|
execute SQL statements to query the database. Such queries
|
||||||
Such queries can be used to confirm database state both
|
can be used to confirm database state both <emphasis>prior
|
||||||
<emphasis>prior to</emphasis> and <emphasis>after</emphasis>
|
to</emphasis> and <emphasis>after</emphasis> execution of
|
||||||
execution of database-related application code, and Spring
|
database-related application code, and Spring ensures that
|
||||||
ensures that such queries run in the scope of the same
|
such queries run in the scope of the same transaction as the
|
||||||
transaction as the application code. When used in
|
application code. When used in conjunction with an ORM tool,
|
||||||
conjunction with an ORM tool, be sure to avoid <link
|
be sure to avoid <link
|
||||||
linkend="testcontext-tx-false-positives">false
|
linkend="testcontext-tx-false-positives">false
|
||||||
positives</link>.</para>
|
positives</link>.</para>
|
||||||
</listitem>
|
</listitem>
|
||||||
|
|
Loading…
Reference in New Issue