Merge from sbrannen/SPR-12051
* SPR-12051: Introduce @TestPropertySource support in the TCF
This commit is contained in:
@@ -53,22 +53,19 @@ import org.springframework.context.ConfigurableApplicationContext;
|
||||
* The term <em>annotated class</em> can refer to any of the following.
|
||||
*
|
||||
* <ul>
|
||||
* <li>A class annotated with @{@link org.springframework.context.annotation.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
|
||||
* {@link org.springframework.stereotype.Component @Component},
|
||||
* {@link org.springframework.stereotype.Service @Service},
|
||||
* {@link org.springframework.stereotype.Repository @Repository}, etc.)</li>
|
||||
* <li>A JSR-330 compliant class that is annotated with {@code javax.inject} annotations</li>
|
||||
* <li>Any other class that contains {@link org.springframework.context.annotation.Bean
|
||||
* @Bean}-methods</li>
|
||||
* <li>Any other class that contains {@link org.springframework.context.annotation.Bean @Bean}-methods</li>
|
||||
* </ul>
|
||||
*
|
||||
* <p>
|
||||
* 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
|
||||
* <em>annotated classes</em>.
|
||||
* 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 <em>annotated classes</em>.
|
||||
*
|
||||
* <p>
|
||||
* As of Spring Framework 4.0, this annotation may be used as a <em>meta-annotation</em>
|
||||
@@ -78,6 +75,7 @@ import org.springframework.context.ConfigurableApplicationContext;
|
||||
* @since 2.5
|
||||
* @see ContextHierarchy
|
||||
* @see ActiveProfiles
|
||||
* @see TestPropertySource
|
||||
* @see ContextLoader
|
||||
* @see SmartContextLoader
|
||||
* @see ContextConfigurationAttributes
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2014 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.
|
||||
@@ -34,15 +34,17 @@ import org.springframework.util.StringUtils;
|
||||
/**
|
||||
* {@code MergedContextConfiguration} encapsulates the <em>merged</em>
|
||||
* context configuration declared on a test class and all of its superclasses
|
||||
* via {@link ContextConfiguration @ContextConfiguration} and
|
||||
* {@link ActiveProfiles @ActiveProfiles}.
|
||||
* via {@link ContextConfiguration @ContextConfiguration},
|
||||
* {@link ActiveProfiles @ActiveProfiles}, and
|
||||
* {@link TestPropertySource @TestPropertySource}.
|
||||
*
|
||||
* <p>Merged resource locations, annotated classes, and active profiles
|
||||
* represent all declared values in the test class hierarchy taking into
|
||||
* consideration the semantics of the
|
||||
* {@link ContextConfiguration#inheritLocations inheritLocations} and
|
||||
* {@link ActiveProfiles#inheritProfiles inheritProfiles} flags in
|
||||
* {@code @ContextConfiguration} and {@code @ActiveProfiles}, respectively.
|
||||
* <p>Merged context resource locations, annotated classes, active profiles,
|
||||
* property resource locations, and in-lined properties represent all declared
|
||||
* values in the test class hierarchy taking into consideration the semantics
|
||||
* of the {@link ContextConfiguration#inheritLocations},
|
||||
* {@link ActiveProfiles#inheritProfiles},
|
||||
* {@link TestPropertySource#inheritLocations}, and
|
||||
* {@link TestPropertySource#inheritProperties} flags.
|
||||
*
|
||||
* <p>A {@link SmartContextLoader} uses {@code MergedContextConfiguration}
|
||||
* to load an {@link org.springframework.context.ApplicationContext ApplicationContext}.
|
||||
@@ -73,13 +75,15 @@ public class MergedContextConfiguration implements Serializable {
|
||||
private final Class<?>[] classes;
|
||||
private final Set<Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>> contextInitializerClasses;
|
||||
private final String[] activeProfiles;
|
||||
private final String[] propertySourceLocations;
|
||||
private final String[] propertySourceProperties;
|
||||
private final ContextLoader contextLoader;
|
||||
private final CacheAwareContextLoaderDelegate cacheAwareContextLoaderDelegate;
|
||||
private final MergedContextConfiguration parent;
|
||||
|
||||
|
||||
private static String[] processLocations(String[] locations) {
|
||||
return locations == null ? EMPTY_STRING_ARRAY : locations;
|
||||
private static String[] processStrings(String[] array) {
|
||||
return array == null ? EMPTY_STRING_ARRAY : array;
|
||||
}
|
||||
|
||||
private static Class<?>[] processClasses(Class<?>[] classes) {
|
||||
@@ -115,20 +119,15 @@ public class MergedContextConfiguration implements Serializable {
|
||||
|
||||
/**
|
||||
* Create a new {@code MergedContextConfiguration} instance for the
|
||||
* supplied test class, resource locations, annotated classes, active
|
||||
* profiles, and {@code ContextLoader}.
|
||||
*
|
||||
* <p>If a {@code null} value is supplied for {@code locations},
|
||||
* {@code classes}, or {@code activeProfiles} an empty array will
|
||||
* be stored instead. Furthermore, active profiles will be sorted, and duplicate
|
||||
* profiles will be removed.
|
||||
* supplied parameters.
|
||||
* <p>Delegates to
|
||||
* {@link #MergedContextConfiguration(Class, String[], Class[], Set, String[], String[], String[], ContextLoader, CacheAwareContextLoaderDelegate, MergedContextConfiguration)}.
|
||||
*
|
||||
* @param testClass the test class for which the configuration was merged
|
||||
* @param locations the merged resource locations
|
||||
* @param locations the merged context resource locations
|
||||
* @param classes the merged annotated classes
|
||||
* @param activeProfiles the merged active bean definition profiles
|
||||
* @param contextLoader the resolved {@code ContextLoader}
|
||||
* @see #MergedContextConfiguration(Class, String[], Class[], Set, String[], ContextLoader)
|
||||
*/
|
||||
public MergedContextConfiguration(Class<?> testClass, String[] locations, Class<?>[] classes,
|
||||
String[] activeProfiles, ContextLoader contextLoader) {
|
||||
@@ -137,18 +136,12 @@ public class MergedContextConfiguration implements Serializable {
|
||||
|
||||
/**
|
||||
* 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} value is supplied for {@code locations},
|
||||
* {@code classes}, or {@code activeProfiles} an empty array will
|
||||
* be stored instead. If a {@code null} value is supplied for the
|
||||
* {@code contextInitializerClasses} an empty set will be stored instead.
|
||||
* Furthermore, active profiles will be sorted, and duplicate profiles will
|
||||
* be removed.
|
||||
* supplied parameters.
|
||||
* <p>Delegates to
|
||||
* {@link #MergedContextConfiguration(Class, String[], Class[], Set, String[], String[], String[], ContextLoader, CacheAwareContextLoaderDelegate, MergedContextConfiguration)}.
|
||||
*
|
||||
* @param testClass the test class for which the configuration was merged
|
||||
* @param locations the merged resource locations
|
||||
* @param locations the merged context resource locations
|
||||
* @param classes the merged annotated classes
|
||||
* @param contextInitializerClasses the merged context initializer classes
|
||||
* @param activeProfiles the merged active bean definition profiles
|
||||
@@ -166,19 +159,12 @@ public class MergedContextConfiguration implements Serializable {
|
||||
|
||||
/**
|
||||
* Create a new {@code MergedContextConfiguration} instance for the
|
||||
* supplied test class, resource locations, annotated classes, context
|
||||
* initializers, active profiles, {@code ContextLoader}, and parent
|
||||
* configuration.
|
||||
*
|
||||
* <p>If a {@code null} value is supplied for {@code locations},
|
||||
* {@code classes}, or {@code activeProfiles} an empty array will
|
||||
* be stored instead. If a {@code null} value is supplied for the
|
||||
* {@code contextInitializerClasses} an empty set will be stored instead.
|
||||
* Furthermore, active profiles will be sorted, and duplicate profiles will
|
||||
* be removed.
|
||||
* supplied parameters.
|
||||
* <p>Delegates to
|
||||
* {@link #MergedContextConfiguration(Class, String[], Class[], Set, String[], String[], String[], ContextLoader, CacheAwareContextLoaderDelegate, MergedContextConfiguration)}.
|
||||
*
|
||||
* @param testClass the test class for which the configuration was merged
|
||||
* @param locations the merged resource locations
|
||||
* @param locations the merged context resource locations
|
||||
* @param classes the merged annotated classes
|
||||
* @param contextInitializerClasses the merged context initializer classes
|
||||
* @param activeProfiles the merged active bean definition profiles
|
||||
@@ -195,11 +181,50 @@ public class MergedContextConfiguration implements Serializable {
|
||||
Set<Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>> contextInitializerClasses,
|
||||
String[] activeProfiles, ContextLoader contextLoader,
|
||||
CacheAwareContextLoaderDelegate cacheAwareContextLoaderDelegate, MergedContextConfiguration parent) {
|
||||
this(testClass, locations, classes, contextInitializerClasses, activeProfiles, null, null, contextLoader,
|
||||
cacheAwareContextLoaderDelegate, parent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@code MergedContextConfiguration} instance for the
|
||||
* supplied parameters.
|
||||
*
|
||||
* <p>If a {@code null} value is supplied for {@code locations},
|
||||
* {@code classes}, {@code activeProfiles}, {@code propertySourceLocations},
|
||||
* or {@code propertySourceProperties} an empty array will be stored instead.
|
||||
* If a {@code null} value is supplied for the
|
||||
* {@code contextInitializerClasses} 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 context resource locations
|
||||
* @param classes the merged annotated classes
|
||||
* @param contextInitializerClasses the merged context initializer classes
|
||||
* @param activeProfiles the merged active bean definition profiles
|
||||
* @param propertySourceLocations the merged {@code PropertySource} locations
|
||||
* @param propertySourceProperties the merged {@code PropertySource} properties
|
||||
* @param contextLoader the resolved {@code ContextLoader}
|
||||
* @param cacheAwareContextLoaderDelegate a cache-aware context loader
|
||||
* delegate with which to retrieve the parent context
|
||||
* @param parent the parent configuration or {@code null} if there is no parent
|
||||
* @since 4.1
|
||||
*/
|
||||
public MergedContextConfiguration(
|
||||
Class<?> testClass,
|
||||
String[] locations,
|
||||
Class<?>[] classes,
|
||||
Set<Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>> contextInitializerClasses,
|
||||
String[] activeProfiles, String[] propertySourceLocations, String[] propertySourceProperties,
|
||||
ContextLoader contextLoader, CacheAwareContextLoaderDelegate cacheAwareContextLoaderDelegate,
|
||||
MergedContextConfiguration parent) {
|
||||
this.testClass = testClass;
|
||||
this.locations = processLocations(locations);
|
||||
this.locations = processStrings(locations);
|
||||
this.classes = processClasses(classes);
|
||||
this.contextInitializerClasses = processContextInitializerClasses(contextInitializerClasses);
|
||||
this.activeProfiles = processActiveProfiles(activeProfiles);
|
||||
this.propertySourceLocations = processStrings(propertySourceLocations);
|
||||
this.propertySourceProperties = processStrings(propertySourceProperties);
|
||||
this.contextLoader = contextLoader;
|
||||
this.cacheAwareContextLoaderDelegate = cacheAwareContextLoaderDelegate;
|
||||
this.parent = parent;
|
||||
@@ -213,7 +238,10 @@ public class MergedContextConfiguration implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the merged resource locations for the {@linkplain #getTestClass() test class}.
|
||||
* Get the merged resource locations for {@code ApplicationContext}
|
||||
* configuration files for the {@linkplain #getTestClass() test class}.
|
||||
* <p>Context resource locations typically represent XML configuration
|
||||
* files or Groovy scripts.
|
||||
*/
|
||||
public String[] getLocations() {
|
||||
return locations;
|
||||
@@ -228,7 +256,7 @@ public class MergedContextConfiguration implements Serializable {
|
||||
|
||||
/**
|
||||
* Determine if this {@code MergedContextConfiguration} instance has
|
||||
* path-based resource locations.
|
||||
* path-based context resource locations.
|
||||
*
|
||||
* @return {@code true} if the {@link #getLocations() locations} array is not empty
|
||||
* @since 4.0.4
|
||||
@@ -254,7 +282,7 @@ public class MergedContextConfiguration implements Serializable {
|
||||
|
||||
/**
|
||||
* Determine if this {@code MergedContextConfiguration} instance has
|
||||
* either path-based resource locations or class-based resources.
|
||||
* either path-based context resource locations or class-based resources.
|
||||
*
|
||||
* @return {@code true} if either the {@link #getLocations() locations}
|
||||
* or the {@link #getClasses() classes} array is not empty
|
||||
@@ -275,12 +303,36 @@ public class MergedContextConfiguration implements Serializable {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the merged active bean definition profiles for the {@linkplain #getTestClass() test class}.
|
||||
* Get the merged active bean definition profiles for the
|
||||
* {@linkplain #getTestClass() test class}.
|
||||
* @see ActiveProfiles
|
||||
*/
|
||||
public String[] getActiveProfiles() {
|
||||
return activeProfiles;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the merged resource locations for test {@code PropertySources} for the
|
||||
* {@linkplain #getTestClass() test class}.
|
||||
* @see TestPropertySource#locations
|
||||
* @see java.util.Properties
|
||||
*/
|
||||
public String[] getPropertySourceLocations() {
|
||||
return propertySourceLocations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the merged test {@code PropertySource} properties for the
|
||||
* {@linkplain #getTestClass() test class}.
|
||||
* <p>Properties will be loaded into the {@code Environment}'s set of
|
||||
* {@code PropertySources}.
|
||||
* @see TestPropertySource#properties
|
||||
* @see java.util.Properties
|
||||
*/
|
||||
public String[] getPropertySourceProperties() {
|
||||
return propertySourceProperties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the resolved {@link ContextLoader} for the {@linkplain #getTestClass() test class}.
|
||||
*/
|
||||
@@ -334,6 +386,8 @@ public class MergedContextConfiguration implements Serializable {
|
||||
result = prime * result + Arrays.hashCode(classes);
|
||||
result = prime * result + contextInitializerClasses.hashCode();
|
||||
result = prime * result + Arrays.hashCode(activeProfiles);
|
||||
result = prime * result + Arrays.hashCode(propertySourceLocations);
|
||||
result = prime * result + Arrays.hashCode(propertySourceProperties);
|
||||
result = prime * result + (parent == null ? 0 : parent.hashCode());
|
||||
result = prime * result + nullSafeToString(contextLoader).hashCode();
|
||||
return result;
|
||||
@@ -345,6 +399,8 @@ public class MergedContextConfiguration implements Serializable {
|
||||
* {@linkplain #getClasses() annotated classes},
|
||||
* {@linkplain #getContextInitializerClasses() context initializer classes},
|
||||
* {@linkplain #getActiveProfiles() active profiles},
|
||||
* {@linkplain #getPropertySourceLocations() property source locations},
|
||||
* {@linkplain #getPropertySourceProperties() property source properties},
|
||||
* {@linkplain #getParent() parents}, and the fully qualified names of their
|
||||
* {@link #getContextLoader() ContextLoaders}.
|
||||
*/
|
||||
@@ -376,6 +432,14 @@ public class MergedContextConfiguration implements Serializable {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Arrays.equals(this.propertySourceLocations, that.propertySourceLocations)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!Arrays.equals(this.propertySourceProperties, that.propertySourceProperties)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.parent == null) {
|
||||
if (that.parent != null) {
|
||||
return false;
|
||||
@@ -396,8 +460,10 @@ public class MergedContextConfiguration implements Serializable {
|
||||
* Provide a String representation of the {@linkplain #getTestClass() test class},
|
||||
* {@linkplain #getLocations() locations}, {@linkplain #getClasses() annotated classes},
|
||||
* {@linkplain #getContextInitializerClasses() context initializer classes},
|
||||
* {@linkplain #getActiveProfiles() active profiles}, the name of the
|
||||
* {@link #getContextLoader() ContextLoader}, and the
|
||||
* {@linkplain #getActiveProfiles() active profiles},
|
||||
* {@linkplain #getPropertySourceLocations() property source locations},
|
||||
* {@linkplain #getPropertySourceProperties() property source properties},
|
||||
* the name of the {@link #getContextLoader() ContextLoader}, and the
|
||||
* {@linkplain #getParent() parent configuration}.
|
||||
*/
|
||||
@Override
|
||||
@@ -408,6 +474,8 @@ public class MergedContextConfiguration implements Serializable {
|
||||
.append("classes", ObjectUtils.nullSafeToString(classes))//
|
||||
.append("contextInitializerClasses", ObjectUtils.nullSafeToString(contextInitializerClasses))//
|
||||
.append("activeProfiles", ObjectUtils.nullSafeToString(activeProfiles))//
|
||||
.append("propertySourceLocations", ObjectUtils.nullSafeToString(propertySourceLocations))//
|
||||
.append("propertySourceProperties", ObjectUtils.nullSafeToString(propertySourceProperties))//
|
||||
.append("contextLoader", nullSafeToString(contextLoader))//
|
||||
.append("parent", parent)//
|
||||
.toString();
|
||||
|
||||
@@ -0,0 +1,250 @@
|
||||
/*
|
||||
* Copyright 2002-2014 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;
|
||||
|
||||
import java.lang.annotation.Documented;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Inherited;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* {@code @TestPropertySource} is a class-level annotation that is used to
|
||||
* configure the {@link #locations} of properties files and inlined
|
||||
* {@link #properties} to be added to the {@code Environment}'s set of
|
||||
* {@code PropertySources} for an
|
||||
* {@link org.springframework.context.ApplicationContext ApplicationContext}
|
||||
* for integration tests.
|
||||
*
|
||||
* <h3>Precedence</h3>
|
||||
* <p>Test property sources have higher precedence than those loaded from the
|
||||
* operating system's environment or Java system properties as well as property
|
||||
* sources added by the application declaratively via
|
||||
* {@link org.springframework.context.annotation.PropertySource @PropertySource}
|
||||
* or programmatically (e.g., via an
|
||||
* {@link org.springframework.context.ApplicationContextInitializer ApplicationContextInitializer}
|
||||
* or some other means). Thus, test property sources can be used to selectively
|
||||
* override properties defined in system and application property sources.
|
||||
* Furthermore, inlined {@link #properties} have higher precedence than
|
||||
* properties loaded from resource {@link #locations}.
|
||||
*
|
||||
* <h3>Default Properties File Detection</h3>
|
||||
* <p>If {@code @TestPropertySource} is declared as an <em>empty</em> annotation
|
||||
* (i.e., without explicit values for {@link #locations} or {@link #properties}),
|
||||
* an attempt will be made to detect a <em>default</em> properties file relative
|
||||
* to the class that declared the annotation. For example, if the annotated test
|
||||
* class is {@code com.example.MyTest}, the corresponding default properties file
|
||||
* is {@code "classpath:com/example/MyTest.properties"}. If the default cannot be
|
||||
* detected, an {@link IllegalStateException} will be thrown.
|
||||
*
|
||||
* <h3>Enabling @TestPropertySource</h3>
|
||||
* <p>{@code @TestPropertySource} is enabled if the configured
|
||||
* {@linkplain ContextConfiguration#loader context loader} honors it. Every
|
||||
* {@code SmartContextLoader} that is a subclass of either
|
||||
* {@link org.springframework.test.context.support.AbstractGenericContextLoader AbstractGenericContextLoader} or
|
||||
* {@link org.springframework.test.context.web.AbstractGenericWebContextLoader AbstractGenericWebContextLoader}
|
||||
* provides automatic support for {@code @TestPropertySource}, and this includes
|
||||
* every {@code SmartContextLoader} provided by the Spring TestContext Framework.
|
||||
*
|
||||
* <h3>Miscellaneous</h3>
|
||||
* <ul>
|
||||
* <li>Typically, {@code @TestPropertySource} will be used in conjunction with
|
||||
* {@link ContextConfiguration @ContextConfiguration}.</li>
|
||||
* <li>This annotation may be used as a <em>meta-annotation</em> to create
|
||||
* custom <em>composed annotations</em>; however, caution should be taken if
|
||||
* this annotation and {@code @ContextConfiguration} are combined on a composed
|
||||
* annotation since the {@code locations} and {@code inheritLocations} attributes
|
||||
* of both annotations can lead to ambiguity during the attribute resolution
|
||||
* process.</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author Sam Brannen
|
||||
* @since 4.1
|
||||
* @see ContextConfiguration
|
||||
* @see org.springframework.core.env.Environment
|
||||
* @see org.springframework.core.env.PropertySource
|
||||
* @see org.springframework.context.annotation.PropertySource
|
||||
*/
|
||||
@Documented
|
||||
@Inherited
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.TYPE)
|
||||
public @interface TestPropertySource {
|
||||
|
||||
/**
|
||||
* Alias for {@link #locations}.
|
||||
*
|
||||
* <p>This attribute may <strong>not</strong> be used in conjunction with
|
||||
* {@link #locations}, but it may be used <em>instead</em> of {@link #locations}.
|
||||
*
|
||||
* @see #locations
|
||||
*/
|
||||
String[] value() default {};
|
||||
|
||||
/**
|
||||
* The resource locations of properties files to be loaded into the
|
||||
* {@code Environment}'s set of {@code PropertySources}. Each location
|
||||
* will be added to the enclosing {@code Environment} as its own property
|
||||
* source, in the order declared.
|
||||
*
|
||||
* <h3>Supported File Formats</h3>
|
||||
* <p>Both traditional and XML-based properties file formats are supported
|
||||
* — for example, {@code "classpath:/com/example/test.properties"}
|
||||
* or {@code "file:/path/to/file.xml"}.
|
||||
*
|
||||
* <h3>Path Resource Semantics</h3>
|
||||
* <p>Each path will be interpreted as a Spring
|
||||
* {@link org.springframework.core.io.Resource Resource}. A plain path
|
||||
* — for example, {@code "test.properties"} — will be treated as a
|
||||
* classpath resource that is <em>relative</em> to the package in which the
|
||||
* test class is defined. A path starting with a slash will be treated as an
|
||||
* <em>absolute</em> classpath resource, for example:
|
||||
* {@code "/org/example/test.xml"}. A path which references a
|
||||
* URL (e.g., a path prefixed with
|
||||
* {@link org.springframework.util.ResourceUtils#CLASSPATH_URL_PREFIX classpath:},
|
||||
* {@link org.springframework.util.ResourceUtils#FILE_URL_PREFIX file:},
|
||||
* {@code http:}, etc.) will be loaded using the specified resource protocol.
|
||||
* Resource location wildcards (e.g. <code>**/*.properties</code>)
|
||||
* are not permitted: each location must evaluate to exactly one
|
||||
* {@code .properties} or {@code .xml} resource.
|
||||
*
|
||||
* <h3>Default Properties File Detection</h3>
|
||||
* <p>See the class-level Javadoc for a discussion on detection of defaults.
|
||||
*
|
||||
* <h3>Precedence</h3>
|
||||
* <p>Properties loaded from resource locations have lower precedence than
|
||||
* inlined {@link #properties}.
|
||||
*
|
||||
* <p>This attribute may <strong>not</strong> be used in conjunction with
|
||||
* {@link #value}, but it may be used <em>instead</em> of {@link #value}.
|
||||
*
|
||||
* @see #inheritLocations
|
||||
* @see #value
|
||||
* @see #properties
|
||||
* @see org.springframework.core.env.PropertySource
|
||||
*/
|
||||
String[] locations() default {};
|
||||
|
||||
/**
|
||||
* Whether or not test property source {@link #locations} from superclasses
|
||||
* should be <em>inherited</em>.
|
||||
*
|
||||
* <p>The default value is {@code true}, which means that a test class will
|
||||
* <em>inherit</em> property source locations defined by a superclass.
|
||||
* Specifically, the property source locations for a test class will be
|
||||
* appended to the list of property source locations defined by a superclass.
|
||||
* Thus, subclasses have the option of <em>extending</em> the list of test
|
||||
* property source locations.
|
||||
*
|
||||
* <p>If {@code inheritLocations} is set to {@code false}, the property
|
||||
* source locations for the test class will <em>shadow</em> and effectively
|
||||
* replace any property source locations defined by a superclass.
|
||||
*
|
||||
* <p>In the following example, the {@code ApplicationContext} for
|
||||
* {@code BaseTest} will be loaded using only the {@code "base.properties"}
|
||||
* file as a test property source. In contrast, the {@code ApplicationContext}
|
||||
* for {@code ExtendedTest} will be loaded using the {@code "base.properties"}
|
||||
* <strong>and</strong> {@code "extended.properties"} files as test property
|
||||
* source locations.
|
||||
* <pre class="code">
|
||||
* @TestPropertySource("base.properties")
|
||||
* @ContextConfiguration
|
||||
* public class BaseTest {
|
||||
* // ...
|
||||
* }
|
||||
*
|
||||
* @TestPropertySource("extended.properties")
|
||||
* @ContextConfiguration
|
||||
* public class ExtendedTest extends BaseTest {
|
||||
* // ...
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @see #locations
|
||||
*/
|
||||
boolean inheritLocations() default true;
|
||||
|
||||
/**
|
||||
* <em>Inlined properties</em> in the form of <em>key-value</em> pairs that
|
||||
* should be added to the Spring
|
||||
* {@link org.springframework.core.env.Environment Environment} before the
|
||||
* {@code ApplicationContext} is loaded for the test. All key-value pairs
|
||||
* will be added to the enclosing {@code Environment} as a single test
|
||||
* {@code PropertySource} with the highest precedence.
|
||||
*
|
||||
* <h3>Supported Syntax</h3>
|
||||
* <p>The supported syntax for key-value pairs is the same as the
|
||||
* syntax defined for entries in a Java
|
||||
* {@linkplain java.util.Properties#load(java.io.Reader) properties file}:
|
||||
* <ul>
|
||||
* <li>{@code "key=value"}</li>
|
||||
* <li>{@code "key:value"}</li>
|
||||
* <li>{@code "key value"}</li>
|
||||
* </ul>
|
||||
*
|
||||
* <h3>Precedence</h3>
|
||||
* <p>Properties declared via this attribute have higher precedence than
|
||||
* properties loaded from resource {@link locations}.
|
||||
*
|
||||
* <p>This attribute may be used in conjunction with {@link #value}
|
||||
* <em>or</em> {@link #locations}.
|
||||
*
|
||||
* @see #inheritProperties
|
||||
* @see #locations
|
||||
* @see org.springframework.core.env.PropertySource
|
||||
*/
|
||||
String[] properties() default {};
|
||||
|
||||
/**
|
||||
* Whether or not inlined test {@link #properties} from superclasses should
|
||||
* be <em>inherited</em>.
|
||||
*
|
||||
* <p>The default value is {@code true}, which means that a test class will
|
||||
* <em>inherit</em> inlined properties defined by a superclass. Specifically,
|
||||
* the inlined properties for a test class will be appended to the list of
|
||||
* inlined properties defined by a superclass. Thus, subclasses have the
|
||||
* option of <em>extending</em> the list of inlined test properties.
|
||||
*
|
||||
* <p>If {@code inheritProperties} is set to {@code false}, the inlined
|
||||
* properties for the test class will <em>shadow</em> and effectively
|
||||
* replace any inlined properties defined by a superclass.
|
||||
*
|
||||
* <p>In the following example, the {@code ApplicationContext} for
|
||||
* {@code BaseTest} will be loaded using only the inlined {@code key1}
|
||||
* property. In contrast, the {@code ApplicationContext} for
|
||||
* {@code ExtendedTest} will be loaded using the inlined {@code key1}
|
||||
* <strong>and</strong> {@code key2} properties.
|
||||
* <pre class="code">
|
||||
* @TestPropertySource(properties = "key1 = value1")
|
||||
* @ContextConfiguration
|
||||
* public class BaseTest {
|
||||
* // ...
|
||||
* }
|
||||
*
|
||||
* @TestPropertySource(properties = "key2 = value2")
|
||||
* @ContextConfiguration
|
||||
* public class ExtendedTest extends BaseTest {
|
||||
* // ...
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @see #properties
|
||||
*/
|
||||
boolean inheritProperties() default true;
|
||||
|
||||
}
|
||||
@@ -16,8 +16,13 @@
|
||||
|
||||
package org.springframework.test.context.support;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
@@ -28,7 +33,12 @@ import org.springframework.context.ApplicationContextInitializer;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.core.GenericTypeResolver;
|
||||
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
|
||||
import org.springframework.core.env.ConfigurableEnvironment;
|
||||
import org.springframework.core.env.MapPropertySource;
|
||||
import org.springframework.core.env.PropertySource;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.support.ResourcePropertySource;
|
||||
import org.springframework.test.context.ContextConfigurationAttributes;
|
||||
import org.springframework.test.context.ContextLoader;
|
||||
import org.springframework.test.context.MergedContextConfiguration;
|
||||
@@ -53,6 +63,7 @@ import org.springframework.util.ResourceUtils;
|
||||
*
|
||||
* @author Sam Brannen
|
||||
* @author Juergen Hoeller
|
||||
* @author Dave Syer
|
||||
* @since 2.5
|
||||
* @see #generateDefaultLocations
|
||||
* @see #getResourceSuffixes
|
||||
@@ -62,6 +73,8 @@ public abstract class AbstractContextLoader implements SmartContextLoader {
|
||||
|
||||
private static final String[] EMPTY_STRING_ARRAY = new String[0];
|
||||
|
||||
private static final String LINE_SEPARATOR = System.getProperty("line.separator");
|
||||
|
||||
private static final Log logger = LogFactory.getLog(AbstractContextLoader.class);
|
||||
|
||||
|
||||
@@ -96,15 +109,24 @@ public abstract class AbstractContextLoader implements SmartContextLoader {
|
||||
* <ul>
|
||||
* <li>Sets the <em>active bean definition profiles</em> from the supplied
|
||||
* {@code MergedContextConfiguration} in the
|
||||
* {@link org.springframework.core.env.Environment Environment} of the context.</li>
|
||||
* {@link org.springframework.core.env.Environment Environment} of the
|
||||
* context.</li>
|
||||
* <li>Adds {@link PropertySource PropertySources} for all
|
||||
* {@linkplain MergedContextConfiguration#getPropertySourceLocations()
|
||||
* resource locations} and
|
||||
* {@linkplain MergedContextConfiguration#getPropertySourceProperties()
|
||||
* inlined properties} from the supplied {@code MergedContextConfiguration}
|
||||
* to the {@code 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
|
||||
* via the {@code MergedContextConfiguration} and instantiates and
|
||||
* {@linkplain ApplicationContextInitializer#initialize invokes} each with the
|
||||
* given application context.</li>
|
||||
* <ul>
|
||||
* <li>Any {@code ApplicationContextInitializers} implementing
|
||||
* {@link org.springframework.core.Ordered Ordered} or annotated with {@link
|
||||
* org.springframework.core.annotation.Order @Order} will be sorted appropriately.</li>
|
||||
* </ul>
|
||||
* </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 context the newly created application context
|
||||
* @param mergedConfig the merged context configuration
|
||||
* @since 3.2
|
||||
@@ -112,10 +134,79 @@ public abstract class AbstractContextLoader implements SmartContextLoader {
|
||||
* @see #loadContext(MergedContextConfiguration)
|
||||
* @see ConfigurableApplicationContext#setId
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
protected void prepareContext(ConfigurableApplicationContext context, MergedContextConfiguration mergedConfig) {
|
||||
context.getEnvironment().setActiveProfiles(mergedConfig.getActiveProfiles());
|
||||
addResourcePropertySourcesToEnvironment(context, mergedConfig);
|
||||
addInlinedPropertiesToEnvironment(context, mergedConfig);
|
||||
invokeApplicationContextInitializers(context, mergedConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 4.1
|
||||
*/
|
||||
private void addResourcePropertySourcesToEnvironment(ConfigurableApplicationContext context,
|
||||
MergedContextConfiguration mergedConfig) {
|
||||
try {
|
||||
ConfigurableEnvironment environment = context.getEnvironment();
|
||||
String[] locations = mergedConfig.getPropertySourceLocations();
|
||||
for (String location : locations) {
|
||||
String resolvedLocation = environment.resolveRequiredPlaceholders(location);
|
||||
Resource resource = context.getResource(resolvedLocation);
|
||||
ResourcePropertySource ps = new ResourcePropertySource(resource);
|
||||
environment.getPropertySources().addFirst(ps);
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new IllegalStateException("Failed to add PropertySource to Environment", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @since 4.1
|
||||
*/
|
||||
private void addInlinedPropertiesToEnvironment(ConfigurableApplicationContext context,
|
||||
MergedContextConfiguration mergedConfig) {
|
||||
String[] keyValuePairs = mergedConfig.getPropertySourceProperties();
|
||||
if (!ObjectUtils.isEmpty(keyValuePairs)) {
|
||||
String name = "test properties " + ObjectUtils.nullSafeToString(keyValuePairs);
|
||||
MapPropertySource ps = new MapPropertySource(name, extractEnvironmentProperties(keyValuePairs));
|
||||
context.getEnvironment().getPropertySources().addFirst(ps);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract environment properties from the supplied key/value pairs.
|
||||
* <p>Parsing of the key/value pairs is achieved by converting all pairs
|
||||
* into a single <em>virtual</em> properties file in memory and delegating
|
||||
* to {@link Properties#load(java.io.Reader)} to parse that virtual file.
|
||||
* <p>This code has been adapted from Spring Boot's
|
||||
* {@link org.springframework.boot.test.SpringApplicationContextLoader SpringApplicationContextLoader}.
|
||||
* @since 4.1
|
||||
*/
|
||||
private Map<String, Object> extractEnvironmentProperties(String[] keyValuePairs) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (String keyValuePair : keyValuePairs) {
|
||||
sb.append(keyValuePair).append(LINE_SEPARATOR);
|
||||
}
|
||||
String content = sb.toString();
|
||||
Properties props = new Properties();
|
||||
try {
|
||||
props.load(new StringReader(content));
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new IllegalStateException("Failed to load test environment properties from: " + content, e);
|
||||
}
|
||||
|
||||
Map<String, Object> properties = new HashMap<String, Object>();
|
||||
for (String name : props.stringPropertyNames()) {
|
||||
properties.put(name, props.getProperty(name));
|
||||
}
|
||||
return properties;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void invokeApplicationContextInitializers(ConfigurableApplicationContext context,
|
||||
MergedContextConfiguration mergedConfig) {
|
||||
Set<Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>> initializerClasses = mergedConfig.getContextInitializerClasses();
|
||||
if (initializerClasses.isEmpty()) {
|
||||
// no ApplicationContextInitializers have been declared -> nothing to do
|
||||
|
||||
@@ -26,7 +26,6 @@ import java.util.Set;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.beans.BeanInstantiationException;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.context.ApplicationContextInitializer;
|
||||
@@ -100,13 +99,14 @@ public abstract class AbstractTestContextBootstrapper implements TestContextBoot
|
||||
Class<TestExecutionListeners> annotationType = TestExecutionListeners.class;
|
||||
List<Class<? extends TestExecutionListener>> classesList = new ArrayList<Class<? extends TestExecutionListener>>();
|
||||
|
||||
AnnotationDescriptor<TestExecutionListeners> descriptor =
|
||||
MetaAnnotationUtils.findAnnotationDescriptor(clazz, annotationType);
|
||||
AnnotationDescriptor<TestExecutionListeners> descriptor = MetaAnnotationUtils.findAnnotationDescriptor(clazz,
|
||||
annotationType);
|
||||
|
||||
// Use defaults?
|
||||
if (descriptor == null) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("@TestExecutionListeners is not present for class [" + clazz.getName() + "]: using defaults.");
|
||||
logger.debug("@TestExecutionListeners is not present for class [" + clazz.getName()
|
||||
+ "]: using defaults.");
|
||||
}
|
||||
classesList.addAll(getDefaultTestExecutionListenerClasses());
|
||||
}
|
||||
@@ -116,19 +116,19 @@ public abstract class AbstractTestContextBootstrapper implements TestContextBoot
|
||||
Class<?> declaringClass = descriptor.getDeclaringClass();
|
||||
AnnotationAttributes annAttrs = descriptor.getAnnotationAttributes();
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace(String.format("Retrieved @TestExecutionListeners attributes [%s] for declaring class [%s].",
|
||||
annAttrs, declaringClass.getName()));
|
||||
logger.trace(String.format(
|
||||
"Retrieved @TestExecutionListeners attributes [%s] for declaring class [%s].", annAttrs,
|
||||
declaringClass.getName()));
|
||||
}
|
||||
|
||||
Class<? extends TestExecutionListener>[] valueListenerClasses =
|
||||
(Class<? extends TestExecutionListener>[]) annAttrs.getClassArray("value");
|
||||
Class<? extends TestExecutionListener>[] listenerClasses =
|
||||
(Class<? extends TestExecutionListener>[]) annAttrs.getClassArray("listeners");
|
||||
Class<? extends TestExecutionListener>[] valueListenerClasses = (Class<? extends TestExecutionListener>[]) annAttrs.getClassArray("value");
|
||||
Class<? extends TestExecutionListener>[] listenerClasses = (Class<? extends TestExecutionListener>[]) annAttrs.getClassArray("listeners");
|
||||
if (!ObjectUtils.isEmpty(valueListenerClasses) && !ObjectUtils.isEmpty(listenerClasses)) {
|
||||
throw new IllegalStateException(String.format("Class [%s] configured with @TestExecutionListeners' " +
|
||||
"'value' [%s] and 'listeners' [%s] attributes. Use one or the other, but not both.",
|
||||
declaringClass.getName(), ObjectUtils.nullSafeToString(valueListenerClasses),
|
||||
ObjectUtils.nullSafeToString(listenerClasses)));
|
||||
throw new IllegalStateException(String.format(
|
||||
"Class [%s] configured with @TestExecutionListeners' "
|
||||
+ "'value' [%s] and 'listeners' [%s] attributes. Use one or the other, but not both.",
|
||||
declaringClass.getName(), ObjectUtils.nullSafeToString(valueListenerClasses),
|
||||
ObjectUtils.nullSafeToString(listenerClasses)));
|
||||
}
|
||||
else if (!ObjectUtils.isEmpty(valueListenerClasses)) {
|
||||
listenerClasses = valueListenerClasses;
|
||||
@@ -138,7 +138,7 @@ public abstract class AbstractTestContextBootstrapper implements TestContextBoot
|
||||
classesList.addAll(0, Arrays.<Class<? extends TestExecutionListener>> asList(listenerClasses));
|
||||
}
|
||||
descriptor = (annAttrs.getBoolean("inheritListeners") ? MetaAnnotationUtils.findAnnotationDescriptor(
|
||||
descriptor.getRootDeclaringClass().getSuperclass(), annotationType) : null);
|
||||
descriptor.getRootDeclaringClass().getSuperclass(), annotationType) : null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -158,10 +158,10 @@ public abstract class AbstractTestContextBootstrapper implements TestContextBoot
|
||||
}
|
||||
if (ncdfe != null) {
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info(String.format("Could not instantiate TestExecutionListener [%s]. " +
|
||||
"Specify custom listener classes or make the default listener classes " +
|
||||
"(and their required dependencies) available. Offending class: [%s]",
|
||||
listenerClass.getName(), ncdfe.getMessage()));
|
||||
logger.info(String.format("Could not instantiate TestExecutionListener [%s]. "
|
||||
+ "Specify custom listener classes or make the default listener classes "
|
||||
+ "(and their required dependencies) available. Offending class: [%s]",
|
||||
listenerClass.getName(), ncdfe.getMessage()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -186,8 +186,8 @@ public abstract class AbstractTestContextBootstrapper implements TestContextBoot
|
||||
}
|
||||
catch (Throwable ex) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Could not load default TestExecutionListener class [" + className +
|
||||
"]. Specify custom listener classes or make the default listener classes available.", ex);
|
||||
logger.debug("Could not load default TestExecutionListener class [" + className
|
||||
+ "]. Specify custom listener classes or make the default listener classes available.", ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -206,15 +206,15 @@ public abstract class AbstractTestContextBootstrapper implements TestContextBoot
|
||||
if (MetaAnnotationUtils.findAnnotationDescriptorForTypes(testClass, ContextConfiguration.class,
|
||||
ContextHierarchy.class) == null) {
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info(String.format("Neither @ContextConfiguration nor @ContextHierarchy found for test class [%s]",
|
||||
testClass.getName()));
|
||||
logger.info(String.format(
|
||||
"Neither @ContextConfiguration nor @ContextHierarchy found for test class [%s]",
|
||||
testClass.getName()));
|
||||
}
|
||||
return new MergedContextConfiguration(testClass, null, null, null, null);
|
||||
}
|
||||
|
||||
if (AnnotationUtils.findAnnotation(testClass, ContextHierarchy.class) != null) {
|
||||
Map<String, List<ContextConfigurationAttributes>> hierarchyMap =
|
||||
ContextLoaderUtils.buildContextHierarchyMap(testClass);
|
||||
Map<String, List<ContextConfigurationAttributes>> hierarchyMap = ContextLoaderUtils.buildContextHierarchyMap(testClass);
|
||||
MergedContextConfiguration parentConfig = null;
|
||||
MergedContextConfiguration mergedConfig = null;
|
||||
|
||||
@@ -228,8 +228,8 @@ public abstract class AbstractTestContextBootstrapper implements TestContextBoot
|
||||
Assert.notEmpty(reversedList, "ContextConfigurationAttributes list must not be empty");
|
||||
Class<?> declaringClass = reversedList.get(0).getDeclaringClass();
|
||||
|
||||
mergedConfig = buildMergedContextConfiguration(
|
||||
declaringClass, reversedList, parentConfig, cacheAwareContextLoaderDelegate);
|
||||
mergedConfig = buildMergedContextConfiguration(declaringClass, reversedList, parentConfig,
|
||||
cacheAwareContextLoaderDelegate);
|
||||
parentConfig = mergedConfig;
|
||||
}
|
||||
|
||||
@@ -238,8 +238,8 @@ public abstract class AbstractTestContextBootstrapper implements TestContextBoot
|
||||
}
|
||||
else {
|
||||
return buildMergedContextConfiguration(testClass,
|
||||
ContextLoaderUtils.resolveContextConfigurationAttributes(testClass), null,
|
||||
cacheAwareContextLoaderDelegate);
|
||||
ContextLoaderUtils.resolveContextConfigurationAttributes(testClass), null,
|
||||
cacheAwareContextLoaderDelegate);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -276,7 +276,7 @@ public abstract class AbstractTestContextBootstrapper implements TestContextBoot
|
||||
for (ContextConfigurationAttributes configAttributes : configAttributesList) {
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace(String.format("Processing locations and classes for context configuration attributes %s",
|
||||
configAttributes));
|
||||
configAttributes));
|
||||
}
|
||||
if (contextLoader instanceof SmartContextLoader) {
|
||||
SmartContextLoader smartContextLoader = (SmartContextLoader) contextLoader;
|
||||
@@ -286,7 +286,7 @@ public abstract class AbstractTestContextBootstrapper implements TestContextBoot
|
||||
}
|
||||
else {
|
||||
String[] processedLocations = contextLoader.processLocations(configAttributes.getDeclaringClass(),
|
||||
configAttributes.getLocations());
|
||||
configAttributes.getLocations());
|
||||
locationsList.addAll(0, Arrays.asList(processedLocations));
|
||||
// Legacy ContextLoaders don't know how to process classes
|
||||
}
|
||||
@@ -300,9 +300,11 @@ public abstract class AbstractTestContextBootstrapper implements TestContextBoot
|
||||
Set<Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>> initializerClasses = //
|
||||
ApplicationContextInitializerUtils.resolveInitializerClasses(configAttributesList);
|
||||
String[] activeProfiles = ActiveProfilesUtils.resolveActiveProfiles(testClass);
|
||||
MergedTestPropertySources mergedTestPropertySources = TestPropertySourceUtils.buildMergedTestPropertySources(testClass);
|
||||
|
||||
return buildMergedContextConfiguration(testClass, locations, classes, initializerClasses, activeProfiles,
|
||||
contextLoader, cacheAwareContextLoaderDelegate, parentConfig);
|
||||
mergedTestPropertySources.getLocations(), mergedTestPropertySources.getProperties(), contextLoader,
|
||||
cacheAwareContextLoaderDelegate, parentConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -334,7 +336,7 @@ public abstract class AbstractTestContextBootstrapper implements TestContextBoot
|
||||
}
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace(String.format("Using ContextLoader class [%s] for test class [%s]",
|
||||
contextLoaderClass.getName(), testClass.getName()));
|
||||
contextLoaderClass.getName(), testClass.getName()));
|
||||
}
|
||||
return BeanUtils.instantiateClass(contextLoaderClass, ContextLoader.class);
|
||||
}
|
||||
@@ -413,6 +415,8 @@ public abstract class AbstractTestContextBootstrapper implements TestContextBoot
|
||||
* @param classes the merged annotated classes
|
||||
* @param initializerClasses the merged context initializer classes
|
||||
* @param activeProfiles the merged active bean definition profiles
|
||||
* @param propertySourceLocations the merged {@code PropertySource} locations
|
||||
* @param propertySourceProperties the merged {@code PropertySource} properties
|
||||
* @param contextLoader the resolved {@code ContextLoader}
|
||||
* @param cacheAwareContextLoaderDelegate the cache-aware context loader delegate
|
||||
* to be provided to the instantiated {@code MergedContextConfiguration}
|
||||
@@ -421,9 +425,12 @@ public abstract class AbstractTestContextBootstrapper implements TestContextBoot
|
||||
* @return the fully initialized {@code MergedContextConfiguration}
|
||||
*/
|
||||
protected abstract MergedContextConfiguration buildMergedContextConfiguration(
|
||||
Class<?> testClass, String[] locations, Class<?>[] classes,
|
||||
Class<?> testClass,
|
||||
String[] locations,
|
||||
Class<?>[] classes,
|
||||
Set<Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>> initializerClasses,
|
||||
String[] activeProfiles, ContextLoader contextLoader,
|
||||
CacheAwareContextLoaderDelegate cacheAwareContextLoaderDelegate, MergedContextConfiguration parentConfig);
|
||||
String[] activeProfiles, String[] propertySourceLocations, String[] propertySourceProperties,
|
||||
ContextLoader contextLoader, CacheAwareContextLoaderDelegate cacheAwareContextLoaderDelegate,
|
||||
MergedContextConfiguration parentConfig);
|
||||
|
||||
}
|
||||
|
||||
@@ -81,16 +81,19 @@ public class DefaultTestContextBootstrapper extends AbstractTestContextBootstrap
|
||||
/**
|
||||
* Builds a standard {@link MergedContextConfiguration}.
|
||||
*/
|
||||
@Override
|
||||
protected MergedContextConfiguration buildMergedContextConfiguration(
|
||||
Class<?> testClass,
|
||||
String[] locations,
|
||||
Class<?>[] classes,
|
||||
Set<Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>> initializerClasses,
|
||||
String[] activeProfiles, ContextLoader contextLoader,
|
||||
CacheAwareContextLoaderDelegate cacheAwareContextLoaderDelegate, MergedContextConfiguration parentConfig) {
|
||||
String[] activeProfiles, String[] propertySourceLocations, String[] propertySourceProperties,
|
||||
ContextLoader contextLoader, CacheAwareContextLoaderDelegate cacheAwareContextLoaderDelegate,
|
||||
MergedContextConfiguration parentConfig) {
|
||||
|
||||
return new MergedContextConfiguration(testClass, locations, classes, initializerClasses, activeProfiles,
|
||||
contextLoader, cacheAwareContextLoaderDelegate, parentConfig);
|
||||
propertySourceLocations, propertySourceProperties, contextLoader, cacheAwareContextLoaderDelegate,
|
||||
parentConfig);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright 2002-2014 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.support;
|
||||
|
||||
import org.springframework.test.context.TestPropertySource;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* {@code MergedTestPropertySources} encapsulates the <em>merged</em>
|
||||
* property sources declared on a test class and all of its superclasses
|
||||
* via {@link TestPropertySource @TestPropertySource}.
|
||||
*
|
||||
* @author Sam Brannen
|
||||
* @since 4.1
|
||||
* @see TestPropertySource
|
||||
*/
|
||||
class MergedTestPropertySources {
|
||||
|
||||
private static final String[] EMPTY_STRING_ARRAY = new String[0];
|
||||
|
||||
private final String[] locations;
|
||||
|
||||
private final String[] properties;
|
||||
|
||||
|
||||
/**
|
||||
* Create an <em>empty</em> {@code MergedTestPropertySources} instance.
|
||||
*/
|
||||
MergedTestPropertySources() {
|
||||
this(EMPTY_STRING_ARRAY, EMPTY_STRING_ARRAY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a {@code MergedTestPropertySources} instance with the supplied
|
||||
* {@code locations} and {@code properties}.
|
||||
* @param locations the resource locations of properties files; may be
|
||||
* empty but never {@code null}
|
||||
* @param properties the properties in the form of {@code key=value} pairs;
|
||||
* may be empty but never {@code null}
|
||||
*/
|
||||
MergedTestPropertySources(String[] locations, String[] properties) {
|
||||
Assert.notNull(locations, "The locations array must not be null");
|
||||
Assert.notNull(properties, "The properties array must not be null");
|
||||
this.locations = locations;
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the resource locations of properties files.
|
||||
* @see TestPropertySource#locations()
|
||||
*/
|
||||
String[] getLocations() {
|
||||
return this.locations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the properties in the form of <em>key-value</em> pairs.
|
||||
* @see TestPropertySource#properties()
|
||||
*/
|
||||
String[] getProperties() {
|
||||
return this.properties;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,209 @@
|
||||
/*
|
||||
* Copyright 2002-2014 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.support;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.core.annotation.AnnotationAttributes;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.core.style.ToStringCreator;
|
||||
import org.springframework.test.context.TestPropertySource;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.ResourceUtils;
|
||||
|
||||
/**
|
||||
* {@code TestPropertySourceAttributes} encapsulates the attributes declared
|
||||
* via {@link TestPropertySource @TestPropertySource}.
|
||||
*
|
||||
* <p>In addition to encapsulating declared attributes,
|
||||
* {@code TestPropertySourceAttributes} also enforces configuration rules
|
||||
* and detects default properties files.
|
||||
*
|
||||
* @author Sam Brannen
|
||||
* @since 4.1
|
||||
* @see TestPropertySource
|
||||
* @see MergedTestPropertySources
|
||||
*/
|
||||
class TestPropertySourceAttributes {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(TestPropertySourceAttributes.class);
|
||||
|
||||
private final Class<?> declaringClass;
|
||||
|
||||
private final String[] locations;
|
||||
|
||||
private final boolean inheritLocations;
|
||||
|
||||
private final String[] properties;
|
||||
|
||||
private final boolean inheritProperties;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new {@code TestPropertySourceAttributes} instance for the
|
||||
* supplied {@link AnnotationAttributes} (parsed from a
|
||||
* {@link TestPropertySource @TestPropertySource} annotation) and
|
||||
* the {@linkplain Class test class} that declared them, enforcing
|
||||
* configuration rules and detecting a default properties file if
|
||||
* necessary.
|
||||
* @param declaringClass the class that declared {@code @TestPropertySource}
|
||||
* @param annAttrs the annotation attributes from which to retrieve the attributes
|
||||
*/
|
||||
TestPropertySourceAttributes(Class<?> declaringClass, AnnotationAttributes annAttrs) {
|
||||
this(declaringClass, resolveLocations(declaringClass, annAttrs.getStringArray("locations"),
|
||||
annAttrs.getStringArray("value")), annAttrs.getBoolean("inheritLocations"),
|
||||
annAttrs.getStringArray("properties"), annAttrs.getBoolean("inheritProperties"));
|
||||
}
|
||||
|
||||
private TestPropertySourceAttributes(Class<?> declaringClass, String[] locations, boolean inheritLocations,
|
||||
String[] properties, boolean inheritProperties) {
|
||||
Assert.notNull(declaringClass, "declaringClass must not be null");
|
||||
|
||||
if (ObjectUtils.isEmpty(locations) && ObjectUtils.isEmpty(properties)) {
|
||||
locations = new String[] { detectDefaultPropertiesFile(declaringClass) };
|
||||
}
|
||||
|
||||
this.declaringClass = declaringClass;
|
||||
this.locations = locations;
|
||||
this.inheritLocations = inheritLocations;
|
||||
this.properties = properties;
|
||||
this.inheritProperties = inheritProperties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@linkplain Class class} that declared {@code @TestPropertySource}.
|
||||
*
|
||||
* @return the declaring class; never {@code null}
|
||||
*/
|
||||
Class<?> getDeclaringClass() {
|
||||
return declaringClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the resource locations that were declared via {@code @TestPropertySource}.
|
||||
*
|
||||
* <p>Note: The returned value may represent a <em>detected default</em>
|
||||
* that does not match the original value declared via {@code @TestPropertySource}.
|
||||
*
|
||||
* @return the resource locations; potentially {@code null} or <em>empty</em>
|
||||
* @see TestPropertySource#value
|
||||
* @see TestPropertySource#locations
|
||||
* @see #setLocations(String[])
|
||||
*/
|
||||
String[] getLocations() {
|
||||
return locations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@code inheritLocations} flag that was declared via {@code @TestPropertySource}.
|
||||
*
|
||||
* @return the {@code inheritLocations} flag
|
||||
* @see TestPropertySource#inheritLocations
|
||||
*/
|
||||
boolean isInheritLocations() {
|
||||
return inheritLocations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the inlined properties that were declared via {@code @TestPropertySource}.
|
||||
*
|
||||
* @return the inlined properties; potentially {@code null} or <em>empty</em>
|
||||
* @see TestPropertySource#properties
|
||||
*/
|
||||
String[] getProperties() {
|
||||
return this.properties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the {@code inheritProperties} flag that was declared via {@code @TestPropertySource}.
|
||||
*
|
||||
* @return the {@code inheritProperties} flag
|
||||
* @see TestPropertySource#inheritProperties
|
||||
*/
|
||||
boolean isInheritProperties() {
|
||||
return this.inheritProperties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide a String representation of the {@code @TestPropertySource}
|
||||
* attributes and declaring class.
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringCreator(this)//
|
||||
.append("declaringClass", declaringClass.getName())//
|
||||
.append("locations", ObjectUtils.nullSafeToString(locations))//
|
||||
.append("inheritLocations", inheritLocations)//
|
||||
.append("properties", ObjectUtils.nullSafeToString(properties))//
|
||||
.append("inheritProperties", inheritProperties)//
|
||||
.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve resource locations from the supplied {@code locations} and
|
||||
* {@code value} arrays, which correspond to attributes of the same names in
|
||||
* the {@link TestPropertySource} annotation.
|
||||
*
|
||||
* @throws IllegalStateException if both the locations and value attributes have been declared
|
||||
*/
|
||||
private static String[] resolveLocations(Class<?> declaringClass, String[] locations, String[] value) {
|
||||
Assert.notNull(declaringClass, "declaringClass must not be null");
|
||||
|
||||
if (!ObjectUtils.isEmpty(value) && !ObjectUtils.isEmpty(locations)) {
|
||||
String msg = String.format("Class [%s] has been configured with @TestPropertySource's 'value' [%s] "
|
||||
+ "and 'locations' [%s] attributes. Only one declaration of resource "
|
||||
+ "locations is permitted per @TestPropertySource annotation.", declaringClass.getName(),
|
||||
ObjectUtils.nullSafeToString(value), ObjectUtils.nullSafeToString(locations));
|
||||
logger.error(msg);
|
||||
throw new IllegalStateException(msg);
|
||||
}
|
||||
else if (!ObjectUtils.isEmpty(value)) {
|
||||
locations = value;
|
||||
}
|
||||
|
||||
return locations;
|
||||
}
|
||||
|
||||
/**
|
||||
* Detect a default properties file for the supplied class, as specified
|
||||
* in the class-level Javadoc for {@link TestPropertySource}.
|
||||
*/
|
||||
private static String detectDefaultPropertiesFile(Class<?> testClass) {
|
||||
String resourcePath = ClassUtils.convertClassNameToResourcePath(testClass.getName()) + ".properties";
|
||||
String prefixedResourcePath = ResourceUtils.CLASSPATH_URL_PREFIX + resourcePath;
|
||||
ClassPathResource classPathResource = new ClassPathResource(resourcePath);
|
||||
|
||||
if (classPathResource.exists()) {
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info(String.format("Detected default properties file \"%s\" for test class [%s]",
|
||||
prefixedResourcePath, testClass.getName()));
|
||||
}
|
||||
return prefixedResourcePath;
|
||||
}
|
||||
else {
|
||||
String msg = String.format("Could not detect default properties file for test [%s]: "
|
||||
+ "%s does not exist. Either declare the 'locations' or 'properties' attributes "
|
||||
+ "of @TestPropertySource or make the default properties file available.", testClass.getName(),
|
||||
classPathResource);
|
||||
logger.error(msg);
|
||||
throw new IllegalStateException(msg);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
* Copyright 2002-2014 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.support;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.core.annotation.AnnotationAttributes;
|
||||
import org.springframework.test.context.TestPropertySource;
|
||||
import org.springframework.test.context.util.TestContextResourceUtils;
|
||||
import org.springframework.test.util.MetaAnnotationUtils.AnnotationDescriptor;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import static org.springframework.test.util.MetaAnnotationUtils.*;
|
||||
|
||||
/**
|
||||
* Utility methods for working with {@link TestPropertySource @TestPropertySource}.
|
||||
*
|
||||
* @author Sam Brannen
|
||||
* @since 4.1
|
||||
* @see TestPropertySource
|
||||
*/
|
||||
abstract class TestPropertySourceUtils {
|
||||
|
||||
private static final Log logger = LogFactory.getLog(TestPropertySourceUtils.class);
|
||||
|
||||
|
||||
private TestPropertySourceUtils() {
|
||||
/* no-op */
|
||||
}
|
||||
|
||||
static MergedTestPropertySources buildMergedTestPropertySources(Class<?> testClass) {
|
||||
Class<TestPropertySource> annotationType = TestPropertySource.class;
|
||||
AnnotationDescriptor<TestPropertySource> descriptor = findAnnotationDescriptor(testClass, annotationType);
|
||||
if (descriptor == null) {
|
||||
return new MergedTestPropertySources();
|
||||
}
|
||||
|
||||
// else...
|
||||
List<TestPropertySourceAttributes> attributesList = resolveTestPropertySourceAttributes(testClass);
|
||||
String[] locations = mergeLocations(attributesList);
|
||||
String[] properties = mergeProperties(attributesList);
|
||||
return new MergedTestPropertySources(locations, properties);
|
||||
}
|
||||
|
||||
private static List<TestPropertySourceAttributes> resolveTestPropertySourceAttributes(Class<?> testClass) {
|
||||
Assert.notNull(testClass, "Class must not be null");
|
||||
|
||||
final List<TestPropertySourceAttributes> attributesList = new ArrayList<TestPropertySourceAttributes>();
|
||||
final Class<TestPropertySource> annotationType = TestPropertySource.class;
|
||||
AnnotationDescriptor<TestPropertySource> descriptor = findAnnotationDescriptor(testClass, annotationType);
|
||||
Assert.notNull(descriptor, String.format(
|
||||
"Could not find an 'annotation declaring class' for annotation type [%s] and class [%s]",
|
||||
annotationType.getName(), testClass.getName()));
|
||||
|
||||
while (descriptor != null) {
|
||||
AnnotationAttributes annAttrs = descriptor.getAnnotationAttributes();
|
||||
Class<?> rootDeclaringClass = descriptor.getRootDeclaringClass();
|
||||
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace(String.format("Retrieved @TestPropertySource attributes [%s] for declaring class [%s].",
|
||||
annAttrs, rootDeclaringClass.getName()));
|
||||
}
|
||||
|
||||
TestPropertySourceAttributes attributes = new TestPropertySourceAttributes(rootDeclaringClass, annAttrs);
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace("Resolved TestPropertySource attributes: " + attributes);
|
||||
}
|
||||
attributesList.add(attributes);
|
||||
|
||||
descriptor = findAnnotationDescriptor(rootDeclaringClass.getSuperclass(), annotationType);
|
||||
}
|
||||
|
||||
return attributesList;
|
||||
}
|
||||
|
||||
private static String[] mergeLocations(List<TestPropertySourceAttributes> attributesList) {
|
||||
final List<String> locations = new ArrayList<String>();
|
||||
|
||||
for (TestPropertySourceAttributes attrs : attributesList) {
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace(String.format("Processing locations for TestPropertySource attributes %s", attrs));
|
||||
}
|
||||
|
||||
String[] locationsArray = TestContextResourceUtils.convertToClasspathResourcePaths(
|
||||
attrs.getDeclaringClass(), attrs.getLocations());
|
||||
locations.addAll(0, Arrays.<String> asList(locationsArray));
|
||||
|
||||
if (!attrs.isInheritLocations()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return StringUtils.toStringArray(locations);
|
||||
}
|
||||
|
||||
private static String[] mergeProperties(List<TestPropertySourceAttributes> attributesList) {
|
||||
final List<String> properties = new ArrayList<String>();
|
||||
|
||||
for (TestPropertySourceAttributes attrs : attributesList) {
|
||||
if (logger.isTraceEnabled()) {
|
||||
logger.trace(String.format("Processing inlined properties for TestPropertySource attributes %s", attrs));
|
||||
}
|
||||
|
||||
properties.addAll(0, Arrays.<String> asList(attrs.getProperties()));
|
||||
|
||||
if (!attrs.isInheritProperties()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return StringUtils.toStringArray(properties);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2014 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.
|
||||
@@ -60,16 +60,9 @@ public class WebMergedContextConfiguration extends MergedContextConfiguration {
|
||||
|
||||
/**
|
||||
* Create a new {@code WebMergedContextConfiguration} instance for the
|
||||
* supplied test class, resource locations, annotated classes, context
|
||||
* initializers, active profiles, resource base path, and {@code ContextLoader}.
|
||||
*
|
||||
* <p>If a {@code null} value is supplied for {@code locations},
|
||||
* {@code classes}, or {@code activeProfiles} an empty array will
|
||||
* be stored instead. If a {@code null} value is supplied for the
|
||||
* {@code contextInitializerClasses} an empty set will be stored instead.
|
||||
* If an <em>empty</em> value is supplied for the {@code resourceBasePath}
|
||||
* an empty string will be used. Furthermore, active profiles will be sorted,
|
||||
* and duplicate profiles will be removed.
|
||||
* supplied parameters.
|
||||
* <p>Delegates to
|
||||
* {@link #WebMergedContextConfiguration(Class, String[], Class[], Set, String[], String[], String[], String, ContextLoader, CacheAwareContextLoaderDelegate, MergedContextConfiguration)}.
|
||||
*
|
||||
* @param testClass the test class for which the configuration was merged
|
||||
* @param locations the merged resource locations
|
||||
@@ -90,22 +83,16 @@ public class WebMergedContextConfiguration extends MergedContextConfiguration {
|
||||
Set<Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>> contextInitializerClasses,
|
||||
String[] activeProfiles, String resourceBasePath, ContextLoader contextLoader) {
|
||||
|
||||
this(testClass, locations, classes, contextInitializerClasses, activeProfiles, resourceBasePath, contextLoader,
|
||||
this(testClass, locations, classes, contextInitializerClasses, activeProfiles, null, null, resourceBasePath,
|
||||
contextLoader,
|
||||
null, null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@code WebMergedContextConfiguration} instance for the
|
||||
* supplied test class, resource locations, annotated classes, context
|
||||
* initializers, active profiles, resource base path, and {@code ContextLoader}.
|
||||
*
|
||||
* <p>If a {@code null} value is supplied for {@code locations},
|
||||
* {@code classes}, or {@code activeProfiles} an empty array will
|
||||
* be stored instead. If a {@code null} value is supplied for the
|
||||
* {@code contextInitializerClasses} an empty set will be stored instead.
|
||||
* If an <em>empty</em> value is supplied for the {@code resourceBasePath}
|
||||
* an empty string will be used. Furthermore, active profiles will be sorted,
|
||||
* and duplicate profiles will be removed.
|
||||
* supplied parameters.
|
||||
* <p>Delegates to
|
||||
* {@link #WebMergedContextConfiguration(Class, String[], Class[], Set, String[], String[], String[], String, ContextLoader, CacheAwareContextLoaderDelegate, MergedContextConfiguration)}.
|
||||
*
|
||||
* @param testClass the test class for which the configuration was merged
|
||||
* @param locations the merged resource locations
|
||||
@@ -118,6 +105,9 @@ public class WebMergedContextConfiguration extends MergedContextConfiguration {
|
||||
* delegate with which to retrieve the parent context
|
||||
* @param parent the parent configuration or {@code null} if there is no parent
|
||||
* @since 3.2.2
|
||||
* @deprecated as of Spring 4.1, use
|
||||
* {@link #WebMergedContextConfiguration(Class, String[], Class[], Set, String[], String[], String[], String, ContextLoader, CacheAwareContextLoaderDelegate, MergedContextConfiguration)}
|
||||
* instead.
|
||||
*/
|
||||
public WebMergedContextConfiguration(
|
||||
Class<?> testClass,
|
||||
@@ -127,8 +117,48 @@ public class WebMergedContextConfiguration extends MergedContextConfiguration {
|
||||
String[] activeProfiles, String resourceBasePath, ContextLoader contextLoader,
|
||||
CacheAwareContextLoaderDelegate cacheAwareContextLoaderDelegate, MergedContextConfiguration parent) {
|
||||
|
||||
super(testClass, locations, classes, contextInitializerClasses, activeProfiles, contextLoader,
|
||||
cacheAwareContextLoaderDelegate, parent);
|
||||
this(testClass, locations, classes, contextInitializerClasses, activeProfiles, null, null, resourceBasePath,
|
||||
contextLoader, cacheAwareContextLoaderDelegate, parent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new {@code WebMergedContextConfiguration} instance for the
|
||||
* supplied parameters.
|
||||
*
|
||||
* <p>If a {@code null} value is supplied for {@code locations},
|
||||
* {@code classes}, {@code activeProfiles}, {@code propertySourceLocations},
|
||||
* or {@code propertySourceProperties} an empty array will be stored instead.
|
||||
* If a {@code null} value is supplied for the
|
||||
* {@code contextInitializerClasses} an empty set will be stored instead.
|
||||
* If an <em>empty</em> value is supplied for the {@code resourceBasePath}
|
||||
* an empty string will be used. 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 propertySourceLocations the merged {@code PropertySource} locations
|
||||
* @param propertySourceProperties the merged {@code PropertySource} properties
|
||||
* @param resourceBasePath the resource path to the root directory of the web application
|
||||
* @param contextLoader the resolved {@code ContextLoader}
|
||||
* @param cacheAwareContextLoaderDelegate a cache-aware context loader
|
||||
* delegate with which to retrieve the parent context
|
||||
* @param parent the parent configuration or {@code null} if there is no parent
|
||||
* @since 4.1
|
||||
*/
|
||||
public WebMergedContextConfiguration(
|
||||
Class<?> testClass,
|
||||
String[] locations,
|
||||
Class<?>[] classes,
|
||||
Set<Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>> contextInitializerClasses,
|
||||
String[] activeProfiles, String[] propertySourceLocations, String[] propertySourceProperties,
|
||||
String resourceBasePath, ContextLoader contextLoader,
|
||||
CacheAwareContextLoaderDelegate cacheAwareContextLoaderDelegate, MergedContextConfiguration parent) {
|
||||
|
||||
super(testClass, locations, classes, contextInitializerClasses, activeProfiles, propertySourceLocations,
|
||||
propertySourceProperties, contextLoader, cacheAwareContextLoaderDelegate, parent);
|
||||
|
||||
this.resourceBasePath = !StringUtils.hasText(resourceBasePath) ? "" : resourceBasePath;
|
||||
}
|
||||
@@ -185,6 +215,8 @@ public class WebMergedContextConfiguration extends MergedContextConfiguration {
|
||||
* {@linkplain #getLocations() locations}, {@linkplain #getClasses() annotated classes},
|
||||
* {@linkplain #getContextInitializerClasses() context initializer classes},
|
||||
* {@linkplain #getActiveProfiles() active profiles},
|
||||
* {@linkplain #getPropertySourceLocations() property source locations},
|
||||
* {@linkplain #getPropertySourceProperties() property source properties},
|
||||
* {@linkplain #getResourceBasePath() resource base path}, the name of the
|
||||
* {@link #getContextLoader() ContextLoader}, and the
|
||||
* {@linkplain #getParent() parent configuration}.
|
||||
@@ -197,6 +229,8 @@ public class WebMergedContextConfiguration extends MergedContextConfiguration {
|
||||
.append("classes", ObjectUtils.nullSafeToString(getClasses()))//
|
||||
.append("contextInitializerClasses", ObjectUtils.nullSafeToString(getContextInitializerClasses()))//
|
||||
.append("activeProfiles", ObjectUtils.nullSafeToString(getActiveProfiles()))//
|
||||
.append("propertySourceLocations", ObjectUtils.nullSafeToString(getPropertySourceLocations()))//
|
||||
.append("propertySourceProperties", ObjectUtils.nullSafeToString(getPropertySourceProperties()))//
|
||||
.append("resourceBasePath", getResourceBasePath())//
|
||||
.append("contextLoader", nullSafeToString(getContextLoader()))//
|
||||
.append("parent", getParent())//
|
||||
|
||||
@@ -89,20 +89,23 @@ public class WebTestContextBootstrapper extends DefaultTestContextBootstrapper {
|
||||
String[] locations,
|
||||
Class<?>[] classes,
|
||||
Set<Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>> initializerClasses,
|
||||
String[] activeProfiles, ContextLoader contextLoader,
|
||||
CacheAwareContextLoaderDelegate cacheAwareContextLoaderDelegate, MergedContextConfiguration parentConfig) {
|
||||
String[] activeProfiles, String[] propertySourceLocations, String[] propertySourceProperties,
|
||||
ContextLoader contextLoader, CacheAwareContextLoaderDelegate cacheAwareContextLoaderDelegate,
|
||||
MergedContextConfiguration parentConfig) {
|
||||
|
||||
WebAppConfiguration webAppConfiguration = AnnotationUtils.findAnnotation(testClass, WebAppConfiguration.class);
|
||||
if (webAppConfiguration != null) {
|
||||
String resourceBasePath = webAppConfiguration.value();
|
||||
|
||||
return new WebMergedContextConfiguration(testClass, locations, classes, initializerClasses, activeProfiles,
|
||||
resourceBasePath, contextLoader, cacheAwareContextLoaderDelegate, parentConfig);
|
||||
propertySourceLocations, propertySourceProperties, resourceBasePath, contextLoader,
|
||||
cacheAwareContextLoaderDelegate, parentConfig);
|
||||
}
|
||||
|
||||
// else...
|
||||
return super.buildMergedContextConfiguration(testClass, locations, classes, initializerClasses, activeProfiles,
|
||||
contextLoader, cacheAwareContextLoaderDelegate, parentConfig);
|
||||
propertySourceLocations, propertySourceProperties, contextLoader, cacheAwareContextLoaderDelegate,
|
||||
parentConfig);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright 2002-2014 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.env;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.PropertySource;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.TestPropertySource;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link TestPropertySource @TestPropertySource}
|
||||
* support with an explicitly named properties file that overrides a
|
||||
* application-level property configured via
|
||||
* {@link PropertySource @PropertySource} on an
|
||||
* {@link Configuration @Configuration} class.
|
||||
*
|
||||
* @author Sam Brannen
|
||||
* @since 4.1
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration
|
||||
@TestPropertySource("ApplicationPropertyOverridePropertiesFileTestPropertySourceTests.properties")
|
||||
public class ApplicationPropertyOverridePropertiesFileTestPropertySourceTests {
|
||||
|
||||
@Autowired
|
||||
protected Environment env;
|
||||
|
||||
|
||||
@Test
|
||||
public void verifyPropertiesAreAvailableInEnvironment() {
|
||||
assertEquals("test override", env.getProperty("explicit"));
|
||||
}
|
||||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
@Configuration
|
||||
@PropertySource("classpath:/org/springframework/test/context/env/explicit.properties")
|
||||
static class Config {
|
||||
/* no user beans required for these tests */
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
explicit = test override
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright 2002-2014 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.env;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.TestPropertySource;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Integration tests that verify detection of a default properties file
|
||||
* when {@link TestPropertySource @TestPropertySource} is <em>empty</em>.
|
||||
*
|
||||
* @author Sam Brannen
|
||||
* @since 4.1
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration
|
||||
@TestPropertySource
|
||||
public class DefaultPropertiesFileDetectionTestPropertySourceTests {
|
||||
|
||||
@Autowired
|
||||
protected Environment env;
|
||||
|
||||
|
||||
@Test
|
||||
public void verifyPropertiesAreAvailableInEnvironment() {
|
||||
// from DefaultPropertiesFileDetectionTestPropertySourceTests.properties
|
||||
assertEnvironmentValue("riddle", "auto detected");
|
||||
}
|
||||
|
||||
protected void assertEnvironmentValue(String key, String expected) {
|
||||
assertEquals("Value of key [" + key + "].", expected, env.getProperty(key));
|
||||
}
|
||||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
@Configuration
|
||||
static class Config {
|
||||
/* no user beans required for these tests */
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
riddle = auto detected
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright 2002-2014 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.env;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.TestPropertySource;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link TestPropertySource @TestPropertySource}
|
||||
* support with an explicitly named properties file.
|
||||
*
|
||||
* @author Sam Brannen
|
||||
* @since 4.1
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration
|
||||
@TestPropertySource("explicit.properties")
|
||||
public class ExplicitPropertiesFileTestPropertySourceTests {
|
||||
|
||||
@Autowired
|
||||
protected Environment env;
|
||||
|
||||
|
||||
@Test
|
||||
public void verifyPropertiesAreAvailableInEnvironment() {
|
||||
String userHomeKey = "user.home";
|
||||
assertEquals(System.getProperty(userHomeKey), env.getProperty(userHomeKey));
|
||||
assertEquals("enigma", env.getProperty("explicit"));
|
||||
}
|
||||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
@Configuration
|
||||
static class Config {
|
||||
/* no user beans required for these tests */
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 2002-2014 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.env;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.test.context.TestPropertySource;
|
||||
|
||||
/**
|
||||
* Integration tests that verify detection of default properties files
|
||||
* when {@link TestPropertySource @TestPropertySource} is <em>empty</em>
|
||||
* at multiple levels within a class hierarchy.
|
||||
*
|
||||
* @author Sam Brannen
|
||||
* @since 4.1
|
||||
*/
|
||||
@TestPropertySource
|
||||
public class ExtendedDefaultPropertiesFileDetectionTestPropertySourceTests extends
|
||||
DefaultPropertiesFileDetectionTestPropertySourceTests {
|
||||
|
||||
@Test
|
||||
public void verifyPropertiesAreAvailableInEnvironment() {
|
||||
super.verifyPropertiesAreAvailableInEnvironment();
|
||||
// from ExtendedDefaultPropertiesFileDetectionTestPropertySourceTests.properties
|
||||
assertEnvironmentValue("enigma", "auto detected");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
enigma = auto detected
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 2002-2014 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.env;
|
||||
|
||||
import org.springframework.test.context.TestPropertySource;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link TestPropertySource @TestPropertySource}
|
||||
* support with an inherited explicitly named properties file that is
|
||||
* referenced using a relative path.
|
||||
*
|
||||
* @author Sam Brannen
|
||||
* @since 4.1
|
||||
*/
|
||||
public class InheritedRelativePathPropertiesFileTestPropertySourceTests extends
|
||||
ExplicitPropertiesFileTestPropertySourceTests {
|
||||
|
||||
/* all tests are in superclass */
|
||||
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* Copyright 2002-2014 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.env;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.TestPropertySource;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link TestPropertySource @TestPropertySource}
|
||||
* support with an inlined properties.
|
||||
*
|
||||
* @author Sam Brannen
|
||||
* @since 4.1
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration
|
||||
@TestPropertySource(properties = { "foo = bar", "enigma: 42" })
|
||||
public class InlinedPropertiesTestPropertySourceTests {
|
||||
|
||||
@Autowired
|
||||
protected Environment env;
|
||||
|
||||
|
||||
@Test
|
||||
public void verifyPropertiesAreAvailableInEnvironment() {
|
||||
assertEquals("bar", env.getProperty("foo"));
|
||||
assertEquals(42, env.getProperty("enigma", Integer.class).intValue());
|
||||
}
|
||||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
@Configuration
|
||||
static class Config {
|
||||
/* no user beans required for these tests */
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright 2002-2014 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.env;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.test.context.TestPropertySource;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Integration tests that verify support for overriding properties from
|
||||
* properties files via inlined properties configured with
|
||||
* {@link TestPropertySource @TestPropertySource}.
|
||||
*
|
||||
* @author Sam Brannen
|
||||
* @since 4.1
|
||||
*/
|
||||
@TestPropertySource(properties = { "explicit = inlined", "extended = inlined1", "extended = inlined2" })
|
||||
public class MergedPropertiesFilesOverriddenByInlinedPropertiesTestPropertySourceTests extends
|
||||
MergedPropertiesFilesTestPropertySourceTests {
|
||||
|
||||
@Test
|
||||
@Override
|
||||
public void verifyPropertiesAreAvailableInEnvironment() {
|
||||
assertEquals("inlined", env.getProperty("explicit"));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Override
|
||||
public void verifyExtendedPropertiesAreAvailableInEnvironment() {
|
||||
assertEquals("inlined2", env.getProperty("extended"));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 2002-2014 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.env;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.test.context.TestPropertySource;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Integration tests that verify support for contributing additional properties
|
||||
* files to the Spring {@code Environment} via {@link TestPropertySource @TestPropertySource}.
|
||||
*
|
||||
* @author Sam Brannen
|
||||
* @since 4.1
|
||||
*/
|
||||
@TestPropertySource("extended.properties")
|
||||
public class MergedPropertiesFilesTestPropertySourceTests extends
|
||||
ExplicitPropertiesFileTestPropertySourceTests {
|
||||
|
||||
@Test
|
||||
public void verifyExtendedPropertiesAreAvailableInEnvironment() {
|
||||
assertEquals(42, env.getProperty("extended", Integer.class).intValue());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright 2002-2014 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.env;
|
||||
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.core.env.Environment;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.TestPropertySource;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link TestPropertySource @TestPropertySource}
|
||||
* support with an explicitly named properties file that overrides a
|
||||
* system property.
|
||||
*
|
||||
* @author Sam Brannen
|
||||
* @since 4.1
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration
|
||||
@TestPropertySource("SystemPropertyOverridePropertiesFileTestPropertySourceTests.properties")
|
||||
public class SystemPropertyOverridePropertiesFileTestPropertySourceTests {
|
||||
|
||||
private static final String KEY = SystemPropertyOverridePropertiesFileTestPropertySourceTests.class.getSimpleName() + ".riddle";
|
||||
|
||||
@Autowired
|
||||
protected Environment env;
|
||||
|
||||
|
||||
@BeforeClass
|
||||
public static void setSystemProperty() {
|
||||
System.setProperty(KEY, "override me!");
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void removeSystemProperty() {
|
||||
System.setProperty(KEY, "");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void verifyPropertiesAreAvailableInEnvironment() {
|
||||
assertEquals("enigma", env.getProperty(KEY));
|
||||
}
|
||||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
@Configuration
|
||||
static class Config {
|
||||
/* no user beans required for these tests */
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
SystemPropertyOverridePropertiesFileTestPropertySourceTests.riddle = enigma
|
||||
1
spring-test/src/test/java/org/springframework/test/context/env/explicit.properties
vendored
Normal file
1
spring-test/src/test/java/org/springframework/test/context/env/explicit.properties
vendored
Normal file
@@ -0,0 +1 @@
|
||||
explicit = enigma
|
||||
1
spring-test/src/test/java/org/springframework/test/context/env/extended.properties
vendored
Normal file
1
spring-test/src/test/java/org/springframework/test/context/env/extended.properties
vendored
Normal file
@@ -0,0 +1 @@
|
||||
extended = 42
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright 2002-2014 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.env.subpackage;
|
||||
|
||||
import org.springframework.test.context.TestPropertySource;
|
||||
import org.springframework.test.context.env.ExplicitPropertiesFileTestPropertySourceTests;
|
||||
|
||||
/**
|
||||
* Integration tests for {@link TestPropertySource @TestPropertySource}
|
||||
* support with an inherited explicitly named properties file that is
|
||||
* referenced using a relative path within a parent package.
|
||||
*
|
||||
* @author Sam Brannen
|
||||
* @since 4.1
|
||||
*/
|
||||
public class SubpackageInheritedRelativePathPropertiesFileTestPropertySourceTests extends
|
||||
ExplicitPropertiesFileTestPropertySourceTests {
|
||||
|
||||
/* all tests are in superclass */
|
||||
|
||||
}
|
||||
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
* Copyright 2002-2014 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.support;
|
||||
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.ExpectedException;
|
||||
import org.springframework.test.context.TestPropertySource;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.*;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.springframework.test.context.support.TestPropertySourceUtils.*;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link TestPropertySourceUtils}.
|
||||
*
|
||||
* @author Sam Brannen
|
||||
* @since 4.1
|
||||
*/
|
||||
public class TestPropertySourceUtilsTests {
|
||||
|
||||
private static final String[] EMPTY_STRING_ARRAY = new String[0];
|
||||
|
||||
@Rule
|
||||
public ExpectedException expectedException = ExpectedException.none();
|
||||
|
||||
|
||||
private void assertMergedTestPropertySources(Class<?> testClass, String[] expectedLocations,
|
||||
String[] expectedProperties) {
|
||||
MergedTestPropertySources mergedPropertySources = buildMergedTestPropertySources(testClass);
|
||||
assertNotNull(mergedPropertySources);
|
||||
assertArrayEquals(expectedLocations, mergedPropertySources.getLocations());
|
||||
assertArrayEquals(expectedProperties, mergedPropertySources.getProperties());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void emptyAnnotation() {
|
||||
expectedException.expect(IllegalStateException.class);
|
||||
expectedException.expectMessage(startsWith("Could not detect default properties file for test"));
|
||||
expectedException.expectMessage(containsString("EmptyPropertySources.properties"));
|
||||
buildMergedTestPropertySources(EmptyPropertySources.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void extendedEmptyAnnotation() {
|
||||
expectedException.expect(IllegalStateException.class);
|
||||
expectedException.expectMessage(startsWith("Could not detect default properties file for test"));
|
||||
expectedException.expectMessage(containsString("ExtendedEmptyPropertySources.properties"));
|
||||
buildMergedTestPropertySources(ExtendedEmptyPropertySources.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void value() {
|
||||
assertMergedTestPropertySources(ValuePropertySources.class, new String[] { "classpath:/value.xml" },
|
||||
EMPTY_STRING_ARRAY);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void locationsAndValueAttributes() {
|
||||
expectedException.expect(IllegalStateException.class);
|
||||
buildMergedTestPropertySources(LocationsAndValuePropertySources.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void locationsAndProperties() {
|
||||
assertMergedTestPropertySources(LocationsAndPropertiesPropertySources.class, new String[] {
|
||||
"classpath:/foo1.xml", "classpath:/foo2.xml" }, new String[] { "k1a=v1a", "k1b: v1b" });
|
||||
}
|
||||
|
||||
@Test
|
||||
public void inheritedLocationsAndProperties() {
|
||||
assertMergedTestPropertySources(InheritedPropertySources.class, new String[] { "classpath:/foo1.xml",
|
||||
"classpath:/foo2.xml" }, new String[] { "k1a=v1a", "k1b: v1b" });
|
||||
}
|
||||
|
||||
@Test
|
||||
public void extendedLocationsAndProperties() {
|
||||
assertMergedTestPropertySources(ExtendedPropertySources.class, new String[] { "classpath:/foo1.xml",
|
||||
"classpath:/foo2.xml", "classpath:/bar1.xml", "classpath:/bar2.xml" }, new String[] { "k1a=v1a",
|
||||
"k1b: v1b", "k2a v2a", "k2b: v2b" });
|
||||
}
|
||||
|
||||
@Test
|
||||
public void overriddenLocations() {
|
||||
assertMergedTestPropertySources(OverriddenLocationsPropertySources.class,
|
||||
new String[] { "classpath:/baz.properties" }, new String[] { "k1a=v1a", "k1b: v1b", "key = value" });
|
||||
}
|
||||
|
||||
@Test
|
||||
public void overriddenProperties() {
|
||||
assertMergedTestPropertySources(OverriddenPropertiesPropertySources.class, new String[] {
|
||||
"classpath:/foo1.xml", "classpath:/foo2.xml", "classpath:/baz.properties" }, new String[] { "key = value" });
|
||||
}
|
||||
|
||||
@Test
|
||||
public void overriddenLocationsAndProperties() {
|
||||
assertMergedTestPropertySources(OverriddenLocationsAndPropertiesPropertySources.class,
|
||||
new String[] { "classpath:/baz.properties" }, new String[] { "key = value" });
|
||||
}
|
||||
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
@TestPropertySource
|
||||
static class EmptyPropertySources {
|
||||
}
|
||||
|
||||
@TestPropertySource
|
||||
static class ExtendedEmptyPropertySources extends EmptyPropertySources {
|
||||
}
|
||||
|
||||
@TestPropertySource(locations = "/foo", value = "/bar")
|
||||
static class LocationsAndValuePropertySources {
|
||||
}
|
||||
|
||||
@TestPropertySource("/value.xml")
|
||||
static class ValuePropertySources {
|
||||
}
|
||||
|
||||
@TestPropertySource(locations = { "/foo1.xml", "/foo2.xml" }, properties = { "k1a=v1a", "k1b: v1b" })
|
||||
static class LocationsAndPropertiesPropertySources {
|
||||
}
|
||||
|
||||
static class InheritedPropertySources extends LocationsAndPropertiesPropertySources {
|
||||
}
|
||||
|
||||
@TestPropertySource(locations = { "/bar1.xml", "/bar2.xml" }, properties = { "k2a v2a", "k2b: v2b" })
|
||||
static class ExtendedPropertySources extends LocationsAndPropertiesPropertySources {
|
||||
}
|
||||
|
||||
@TestPropertySource(locations = "/baz.properties", properties = "key = value", inheritLocations = false)
|
||||
static class OverriddenLocationsPropertySources extends LocationsAndPropertiesPropertySources {
|
||||
}
|
||||
|
||||
@TestPropertySource(locations = "/baz.properties", properties = "key = value", inheritProperties = false)
|
||||
static class OverriddenPropertiesPropertySources extends LocationsAndPropertiesPropertySources {
|
||||
}
|
||||
|
||||
@TestPropertySource(locations = "/baz.properties", properties = "key = value", inheritLocations = false, inheritProperties = false)
|
||||
static class OverriddenLocationsAndPropertiesPropertySources extends LocationsAndPropertiesPropertySources {
|
||||
}
|
||||
|
||||
}
|
||||
@@ -38,6 +38,7 @@ public class AnnotationConfigWebContextLoaderTests {
|
||||
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("deprecation")
|
||||
public void configMustNotContainLocations() throws Exception {
|
||||
expectedException.expect(IllegalStateException.class);
|
||||
expectedException.expectMessage(containsString("does not support resource locations"));
|
||||
|
||||
@@ -37,6 +37,7 @@ public class GenericXmlWebContextLoaderTests {
|
||||
|
||||
|
||||
@Test
|
||||
@SuppressWarnings("deprecation")
|
||||
public void configMustNotContainAnnotatedClasses() throws Exception {
|
||||
expectedException.expect(IllegalStateException.class);
|
||||
expectedException.expectMessage(containsString("does not support annotated classes"));
|
||||
|
||||
Reference in New Issue
Block a user