null
)
* @param context the ApplicationContext instance (never null
)
*/
@@ -188,11 +187,11 @@ class ContextCache {
* as the {@link #hitCount hit} and {@link #missCount miss} counts.
*/
public String toString() {
- return new ToStringCreator(this)
- .append("size", size())
- .append("hitCount", getHitCount())
- .append("missCount",getMissCount())
- .toString();
+ return new ToStringCreator(this)//
+ .append("size", size())//
+ .append("hitCount", getHitCount())//
+ .append("missCount", getMissCount())//
+ .toString();
}
}
diff --git a/org.springframework.test/src/main/java/org/springframework/test/context/TestContext.java b/org.springframework.test/src/main/java/org/springframework/test/context/TestContext.java
index 4df8d87c67128a97ed2be8150a477b29d094567c..b5adae9916f36710ce15e6c43b80a8552ca39af6 100644
--- a/org.springframework.test/src/main/java/org/springframework/test/context/TestContext.java
+++ b/org.springframework.test/src/main/java/org/springframework/test/context/TestContext.java
@@ -16,7 +16,6 @@
package org.springframework.test.context;
-import java.io.Serializable;
import java.lang.reflect.Method;
import org.apache.commons.logging.Log;
@@ -43,9 +42,9 @@ public class TestContext extends AttributeAccessorSupport {
private final ContextCache contextCache;
- private final ContextLoader contextLoader;
+ private final String contextKey;
- private final String[] locations;
+ private final MergedContextConfiguration mergedContextConfiguration;
private final Class> testClass;
@@ -88,28 +87,28 @@ public class TestContext extends AttributeAccessorSupport {
Assert.notNull(testClass, "Test class must not be null");
Assert.notNull(contextCache, "ContextCache must not be null");
+ MergedContextConfiguration mergedContextConfiguration;
ContextConfiguration contextConfiguration = testClass.getAnnotation(ContextConfiguration.class);
- ContextLoader contextLoader = null;
- String[] locations = null;
if (contextConfiguration == null) {
if (logger.isInfoEnabled()) {
logger.info(String.format("@ContextConfiguration not found for class [%s]", testClass));
}
+ mergedContextConfiguration = new MergedContextConfiguration(testClass, null, null, null, null);
}
else {
if (logger.isTraceEnabled()) {
logger.trace(String.format("Retrieved @ContextConfiguration [%s] for class [%s]", contextConfiguration,
testClass));
}
- contextLoader = ContextLoaderUtils.resolveContextLoader(testClass, defaultContextLoaderClassName);
- locations = ContextLoaderUtils.resolveContextLocations(contextLoader, testClass);
+ mergedContextConfiguration = ContextLoaderUtils.buildMergedContextConfiguration(testClass,
+ defaultContextLoaderClassName);
}
- this.testClass = testClass;
this.contextCache = contextCache;
- this.contextLoader = contextLoader;
- this.locations = locations;
+ this.contextKey = generateContextKey(mergedContextConfiguration);
+ this.mergedContextConfiguration = mergedContextConfiguration;
+ this.testClass = testClass;
}
/**
@@ -118,19 +117,44 @@ public class TestContext extends AttributeAccessorSupport {
* @throws Exception if an error occurs while loading the application context
*/
private ApplicationContext loadApplicationContext() throws Exception {
- Assert.notNull(this.contextLoader, "Can not load an ApplicationContext with a NULL 'contextLoader'. "
- + "Consider annotating your test class with @ContextConfiguration.");
- Assert.notNull(this.locations, "Can not load an ApplicationContext with a NULL 'locations' array. "
+ ContextLoader contextLoader = mergedContextConfiguration.getContextLoader();
+ Assert.notNull(contextLoader, "Can not load an ApplicationContext with a NULL 'contextLoader'. "
+ "Consider annotating your test class with @ContextConfiguration.");
- return this.contextLoader.loadContext(this.locations);
+
+ ApplicationContext applicationContext;
+
+ if (contextLoader instanceof SmartContextLoader) {
+ SmartContextLoader smartContextLoader = (SmartContextLoader) contextLoader;
+ applicationContext = smartContextLoader.loadContext(mergedContextConfiguration);
+ }
+ else {
+ String[] locations = mergedContextConfiguration.getLocations();
+ Assert.notNull(locations, "Can not load an ApplicationContext with a NULL 'locations' array. "
+ + "Consider annotating your test class with @ContextConfiguration.");
+ applicationContext = contextLoader.loadContext(locations);
+ }
+
+ return applicationContext;
}
/**
- * Convert the supplied context key
to a String representation
- * for use in caching, logging, etc.
+ * Generates a context key
from information stored in the
+ * {@link MergedContextConfiguration} for this TestContext
.
*/
- private String contextKeyString(Serializable key) {
- return ObjectUtils.nullSafeToString(key);
+ private String generateContextKey(MergedContextConfiguration mergedContextConfiguration) {
+
+ String[] locations = mergedContextConfiguration.getLocations();
+ Class>[] classes = mergedContextConfiguration.getClasses();
+ String[] activeProfiles = mergedContextConfiguration.getActiveProfiles();
+ ContextLoader contextLoader = mergedContextConfiguration.getContextLoader();
+
+ String locationsKey = ObjectUtils.nullSafeToString(locations);
+ String classesKey = ObjectUtils.nullSafeToString(classes);
+ String activeProfilesKey = ObjectUtils.nullSafeToString(activeProfiles);
+ String contextLoaderKey = contextLoader == null ? "null" : contextLoader.getClass().getName();
+
+ return String.format("locations = [%s], classes = [%s], activeProfiles = [%s], contextLoader = [%s]",
+ locationsKey, classesKey, activeProfilesKey, contextLoaderKey);
}
/**
@@ -141,13 +165,12 @@ public class TestContext extends AttributeAccessorSupport {
* application context
*/
public ApplicationContext getApplicationContext() {
- synchronized (this.contextCache) {
- String contextKeyString = contextKeyString(this.locations);
- ApplicationContext context = this.contextCache.get(contextKeyString);
+ synchronized (contextCache) {
+ ApplicationContext context = contextCache.get(contextKey);
if (context == null) {
try {
context = loadApplicationContext();
- this.contextCache.put(contextKeyString, context);
+ contextCache.put(contextKey, context);
}
catch (Exception ex) {
throw new IllegalStateException("Failed to load ApplicationContext", ex);
@@ -162,7 +185,7 @@ public class TestContext extends AttributeAccessorSupport {
* @return the test class (never null
)
*/
public final Class> getTestClass() {
- return this.testClass;
+ return testClass;
}
/**
@@ -172,7 +195,7 @@ public class TestContext extends AttributeAccessorSupport {
* @see #updateState(Object,Method,Throwable)
*/
public final Object getTestInstance() {
- return this.testInstance;
+ return testInstance;
}
/**
@@ -182,7 +205,7 @@ public class TestContext extends AttributeAccessorSupport {
* @see #updateState(Object, Method, Throwable)
*/
public final Method getTestMethod() {
- return this.testMethod;
+ return testMethod;
}
/**
@@ -194,7 +217,7 @@ public class TestContext extends AttributeAccessorSupport {
* @see #updateState(Object, Method, Throwable)
*/
public final Throwable getTestException() {
- return this.testException;
+ return testException;
}
/**
@@ -204,7 +227,7 @@ public class TestContext extends AttributeAccessorSupport {
* replacing a bean definition).
*/
public void markApplicationContextDirty() {
- this.contextCache.setDirty(contextKeyString(this.locations));
+ contextCache.setDirty(contextKey);
}
/**
@@ -227,11 +250,11 @@ public class TestContext extends AttributeAccessorSupport {
@Override
public String toString() {
return new ToStringCreator(this)//
- .append("testClass", this.testClass)//
- .append("locations", this.locations)//
- .append("testInstance", this.testInstance)//
- .append("testMethod", this.testMethod)//
- .append("testException", this.testException)//
+ .append("testClass", testClass)//
+ .append("testInstance", testInstance)//
+ .append("testMethod", testMethod)//
+ .append("testException", testException)//
+ .append("mergedContextConfiguration", mergedContextConfiguration)//
.toString();
}
diff --git a/org.springframework.test/src/main/java/org/springframework/test/context/support/AbstractContextLoader.java b/org.springframework.test/src/main/java/org/springframework/test/context/support/AbstractContextLoader.java
index 0ce020b82f2b59ddc7c2c4cdbc473f313b8dd164..03c61e56ff09698bd9a9776f81011a1e19315f78 100644
--- a/org.springframework.test/src/main/java/org/springframework/test/context/support/AbstractContextLoader.java
+++ b/org.springframework.test/src/main/java/org/springframework/test/context/support/AbstractContextLoader.java
@@ -20,6 +20,7 @@ import org.springframework.context.ApplicationContext;
import org.springframework.core.io.support.ResourcePatternUtils;
import org.springframework.test.context.ContextLoader;
import org.springframework.test.context.ResourceTypeAwareContextLoader;
+import org.springframework.test.context.SmartContextLoader;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.ObjectUtils;
@@ -38,7 +39,7 @@ import org.springframework.util.StringUtils;
* @see #generateDefaultLocations
* @see #modifyLocations
*/
-public abstract class AbstractContextLoader implements ResourceTypeAwareContextLoader {
+public abstract class AbstractContextLoader implements SmartContextLoader, ResourceTypeAwareContextLoader {
/**
* If the supplied locations
are null
or
diff --git a/org.springframework.test/src/main/java/org/springframework/test/context/support/AbstractGenericContextLoader.java b/org.springframework.test/src/main/java/org/springframework/test/context/support/AbstractGenericContextLoader.java
index 83867996eee5bfc4025ed6ecae1729bca904fd25..9fbb46c223da3211e9e59d60a25f8f5b3f00066e 100644
--- a/org.springframework.test/src/main/java/org/springframework/test/context/support/AbstractGenericContextLoader.java
+++ b/org.springframework.test/src/main/java/org/springframework/test/context/support/AbstractGenericContextLoader.java
@@ -20,9 +20,12 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.support.BeanDefinitionReader;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
+import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigUtils;
import org.springframework.context.support.GenericApplicationContext;
+import org.springframework.test.context.MergedContextConfiguration;
+import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
/**
@@ -45,6 +48,33 @@ public abstract class AbstractGenericContextLoader extends AbstractContextLoader
protected static final Log logger = LogFactory.getLog(AbstractGenericContextLoader.class);
+ /**
+ * TODO Document loadContext().
+ *
+ * @see org.springframework.test.context.SmartContextLoader#loadContext(org.springframework.test.context.MergedContextConfiguration)
+ */
+ public final ApplicationContext loadContext(MergedContextConfiguration mergedContextConfiguration) throws Exception {
+ if (logger.isDebugEnabled()) {
+ logger.debug(String.format("Loading ApplicationContext for merged context configuration [%s].",
+ mergedContextConfiguration));
+ }
+
+ String[] locations = mergedContextConfiguration.getLocations();
+ Assert.notNull(locations, "Can not load an ApplicationContext with a NULL 'locations' array. "
+ + "Consider annotating your test class with @ContextConfiguration.");
+
+ GenericApplicationContext context = new GenericApplicationContext();
+ context.getEnvironment().setActiveProfiles(mergedContextConfiguration.getActiveProfiles());
+ prepareContext(context);
+ customizeBeanFactory(context.getDefaultListableBeanFactory());
+ loadBeanDefinitions(context, locations);
+ AnnotationConfigUtils.registerAnnotationConfigProcessors(context);
+ customizeContext(context);
+ context.refresh();
+ context.registerShutdownHook();
+ return context;
+ }
+
/**
* Loads a Spring ApplicationContext from the supplied locations
.
* Implementation details: diff --git a/org.springframework.test/src/test/java/org/springframework/test/context/junit4/SpringJUnit4SuiteTests.java b/org.springframework.test/src/test/java/org/springframework/test/context/junit4/SpringJUnit4SuiteTests.java index aa29fcecc604be86e26138fcc4799f2f2abc9ec2..573ede18d92de3bd2468269889e90c4340cf8289 100644 --- a/org.springframework.test/src/test/java/org/springframework/test/context/junit4/SpringJUnit4SuiteTests.java +++ b/org.springframework.test/src/test/java/org/springframework/test/context/junit4/SpringJUnit4SuiteTests.java @@ -25,6 +25,10 @@ import org.springframework.test.context.junit4.annotation.AnnotationConfigSpring import org.springframework.test.context.junit4.annotation.DefaultConfigClassesBaseTests; import org.springframework.test.context.junit4.annotation.DefaultConfigClassesInheritedTests; import org.springframework.test.context.junit4.orm.HibernateSessionFlushingTests; +import org.springframework.test.context.junit4.profile.annotation.DefaultProfileAnnotationConfigTests; +import org.springframework.test.context.junit4.profile.annotation.DevProfileAnnotationConfigTests; +import org.springframework.test.context.junit4.profile.xml.DefaultProfileXmlConfigTests; +import org.springframework.test.context.junit4.profile.xml.DevProfileXmlConfigTests; /** *
@@ -54,6 +58,10 @@ StandardJUnit4FeaturesTests.class,//
AnnotationConfigSpringJUnit4ClassRunnerAppCtxTests.class,//
DefaultConfigClassesBaseTests.class,//
DefaultConfigClassesInheritedTests.class,//
+ DefaultProfileAnnotationConfigTests.class,//
+ DevProfileAnnotationConfigTests.class, //
+ DefaultProfileXmlConfigTests.class,//
+ DevProfileXmlConfigTests.class, //
ExpectedExceptionSpringRunnerTests.class,//
TimedSpringRunnerTests.class,//
RepeatedSpringRunnerTests.class,//
diff --git a/org.springframework.test/src/test/java/org/springframework/test/context/junit4/profile/annotation/DefaultProfileAnnotationConfigTests.java b/org.springframework.test/src/test/java/org/springframework/test/context/junit4/profile/annotation/DefaultProfileAnnotationConfigTests.java
new file mode 100644
index 0000000000000000000000000000000000000000..cc26b849dbbeae5dfccfad0fbc8fe0386c8dad03
--- /dev/null
+++ b/org.springframework.test/src/test/java/org/springframework/test/context/junit4/profile/annotation/DefaultProfileAnnotationConfigTests.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.test.context.junit4.profile.annotation;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.beans.Employee;
+import org.springframework.beans.Pet;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.test.context.support.AnnotationConfigContextLoader;
+
+/**
+ * @author Sam Brannen
+ * @since 3.1
+ */
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(classes = { DefaultProfileConfig.class, DevProfileConfig.class }, loader = AnnotationConfigContextLoader.class)
+public class DefaultProfileAnnotationConfigTests {
+
+ @Autowired
+ protected Pet pet;
+
+ @Autowired(required = false)
+ protected Employee employee;
+
+
+ @Test
+ public void pet() {
+ assertNotNull(pet);
+ assertEquals("Fido", pet.getName());
+ }
+
+ @Test
+ public void employee() {
+ assertNull("employee bean should not be created for the default profile", employee);
+ }
+
+}
diff --git a/org.springframework.test/src/test/java/org/springframework/test/context/junit4/profile/annotation/DefaultProfileConfig.java b/org.springframework.test/src/test/java/org/springframework/test/context/junit4/profile/annotation/DefaultProfileConfig.java
new file mode 100644
index 0000000000000000000000000000000000000000..98cc3af14954e0abfdc1f0a35d3f9284f517f904
--- /dev/null
+++ b/org.springframework.test/src/test/java/org/springframework/test/context/junit4/profile/annotation/DefaultProfileConfig.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.test.context.junit4.profile.annotation;
+
+import org.springframework.beans.Pet;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+/**
+ * @author Sam Brannen
+ * @since 3.1
+ */
+@Configuration
+public class DefaultProfileConfig {
+
+ @Bean
+ public Pet pet() {
+ return new Pet("Fido");
+ }
+
+}
diff --git a/org.springframework.test/src/test/java/org/springframework/test/context/junit4/profile/annotation/DevProfileAnnotationConfigTests.java b/org.springframework.test/src/test/java/org/springframework/test/context/junit4/profile/annotation/DevProfileAnnotationConfigTests.java
new file mode 100644
index 0000000000000000000000000000000000000000..4c57ffc3de24604c216e6a802ebee1ddc4d4698d
--- /dev/null
+++ b/org.springframework.test/src/test/java/org/springframework/test/context/junit4/profile/annotation/DevProfileAnnotationConfigTests.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.test.context.junit4.profile.annotation;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import org.junit.Test;
+import org.springframework.test.context.ActiveProfiles;
+
+/**
+ * @author Sam Brannen
+ * @since 3.1
+ */
+@ActiveProfiles("dev")
+public class DevProfileAnnotationConfigTests extends DefaultProfileAnnotationConfigTests {
+
+ @Test
+ public void employee() {
+ assertNotNull("employee bean should be loaded for the 'dev' profile", employee);
+ assertEquals("John Smith", employee.getName());
+ }
+
+}
diff --git a/org.springframework.test/src/test/java/org/springframework/test/context/junit4/profile/annotation/DevProfileConfig.java b/org.springframework.test/src/test/java/org/springframework/test/context/junit4/profile/annotation/DevProfileConfig.java
new file mode 100644
index 0000000000000000000000000000000000000000..9fb695889aef9c7b783a1c2f2fc35c6ebef82c68
--- /dev/null
+++ b/org.springframework.test/src/test/java/org/springframework/test/context/junit4/profile/annotation/DevProfileConfig.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.test.context.junit4.profile.annotation;
+
+import org.springframework.beans.Employee;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Profile;
+
+/**
+ * @author Sam Brannen
+ * @since 3.1
+ */
+@Profile("dev")
+@Configuration
+public class DevProfileConfig {
+
+ @Bean
+ public Employee employee() {
+ Employee employee = new Employee();
+ employee.setName("John Smith");
+ employee.setAge(42);
+ employee.setCompany("Acme Widgets, Inc.");
+ return employee;
+ }
+
+}
diff --git a/org.springframework.test/src/test/java/org/springframework/test/context/junit4/profile/annotation/ProfileAnnotationConfigTestSuite.java b/org.springframework.test/src/test/java/org/springframework/test/context/junit4/profile/annotation/ProfileAnnotationConfigTestSuite.java
new file mode 100644
index 0000000000000000000000000000000000000000..bfc462db600d8a6e06edd6280f97bb2ad4bde5bb
--- /dev/null
+++ b/org.springframework.test/src/test/java/org/springframework/test/context/junit4/profile/annotation/ProfileAnnotationConfigTestSuite.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright 2002-2011 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.springframework.test.context.junit4.profile.annotation;
+
+import org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+import org.junit.runners.Suite.SuiteClasses;
+
+/**
+ * JUnit test suite for bean definition profile support in the
+ * Spring TestContext Framework with XML-based configuration.
+ *
+ * @author Sam Brannen
+ * @since 3.1
+ */
+@RunWith(Suite.class)
+// Note: the following 'multi-line' layout is for enhanced code readability.
+@SuiteClasses({//
+DefaultProfileAnnotationConfigTests.class,//
+ DevProfileAnnotationConfigTests.class //
+})
+public class ProfileAnnotationConfigTestSuite {
+}
diff --git a/org.springframework.test/src/test/java/org/springframework/test/context/junit4/profile/xml/DefaultProfileXmlConfigTests-context.xml b/org.springframework.test/src/test/java/org/springframework/test/context/junit4/profile/xml/DefaultProfileXmlConfigTests-context.xml
new file mode 100644
index 0000000000000000000000000000000000000000..1fc6d4ecfc955b4fbca266a30e44988a7d9ef888
--- /dev/null
+++ b/org.springframework.test/src/test/java/org/springframework/test/context/junit4/profile/xml/DefaultProfileXmlConfigTests-context.xml
@@ -0,0 +1,17 @@
+
+