提交 f874ed97 编写于 作者: S Sam Brannen

[SPR-8387] Fleshed out the implementation of DelegatingSmartContextLoader and corresponding tests.

上级 9d7bc31f
......@@ -102,6 +102,10 @@ public class ContextConfigurationAttributes {
*/
public ContextConfigurationAttributes(Class<?> declaringClass, String[] locations, Class<?>[] classes,
boolean inheritLocations, Class<? extends ContextLoader> contextLoaderClass) {
Assert.notNull(declaringClass, "declaringClass must not be null");
Assert.notNull(contextLoaderClass, "contextLoaderClass must not be null");
this.declaringClass = declaringClass;
this.locations = locations;
this.classes = classes;
......@@ -115,7 +119,7 @@ public class ContextConfigurationAttributes {
* @return the declaring class; never <code>null</code>
*/
public Class<?> getDeclaringClass() {
return this.declaringClass;
return declaringClass;
}
/**
......@@ -130,7 +134,7 @@ public class ContextConfigurationAttributes {
* @see #setLocations()
*/
public String[] getLocations() {
return this.locations;
return locations;
}
/**
......@@ -153,7 +157,7 @@ public class ContextConfigurationAttributes {
* @see #setClasses()
*/
public Class<?>[] getClasses() {
return this.classes;
return classes;
}
/**
......@@ -184,7 +188,7 @@ public class ContextConfigurationAttributes {
* @see ContextConfiguration#inheritLocations
*/
public boolean isInheritLocations() {
return this.inheritLocations;
return inheritLocations;
}
/**
......@@ -194,7 +198,7 @@ public class ContextConfigurationAttributes {
* @see ContextConfiguration#loader
*/
public Class<? extends ContextLoader> getContextLoaderClass() {
return this.contextLoaderClass;
return contextLoaderClass;
}
/**
......@@ -204,11 +208,11 @@ public class ContextConfigurationAttributes {
@Override
public String toString() {
return new ToStringCreator(this)//
.append("declaringClass", this.declaringClass)//
.append("locations", ObjectUtils.nullSafeToString(this.locations))//
.append("classes", ObjectUtils.nullSafeToString(this.classes))//
.append("inheritLocations", this.inheritLocations)//
.append("contextLoaderClass", this.contextLoaderClass)//
.append("declaringClass", declaringClass.getName())//
.append("locations", ObjectUtils.nullSafeToString(locations))//
.append("classes", ObjectUtils.nullSafeToString(classes))//
.append("inheritLocations", inheritLocations)//
.append("contextLoaderClass", contextLoaderClass.getName())//
.toString();
}
......
......@@ -136,7 +136,7 @@ public class MergedContextConfiguration {
* <code>MergedContextConfiguration</code>.
*/
public Class<?> getTestClass() {
return this.testClass;
return testClass;
}
/**
......@@ -144,7 +144,7 @@ public class MergedContextConfiguration {
* {@link #getTestClass() test class}.
*/
public String[] getLocations() {
return this.locations;
return locations;
}
/**
......@@ -152,7 +152,7 @@ public class MergedContextConfiguration {
* {@link #getTestClass() test class}.
*/
public Class<?>[] getClasses() {
return this.classes;
return classes;
}
/**
......@@ -160,7 +160,7 @@ public class MergedContextConfiguration {
* {@link #getTestClass() test class}.
*/
public String[] getActiveProfiles() {
return this.activeProfiles;
return activeProfiles;
}
/**
......@@ -168,7 +168,7 @@ public class MergedContextConfiguration {
* {@link #getTestClass() test class}.
*/
public ContextLoader getContextLoader() {
return this.contextLoader;
return contextLoader;
}
/**
......@@ -180,7 +180,7 @@ public class MergedContextConfiguration {
* that was loaded using properties of this <code>MergedContextConfiguration</code>.
*/
public String getContextKey() {
return this.contextKey;
return contextKey;
}
/**
......@@ -190,12 +190,12 @@ public class MergedContextConfiguration {
@Override
public String toString() {
return new ToStringCreator(this)//
.append("testClass", this.testClass)//
.append("locations", ObjectUtils.nullSafeToString(this.locations))//
.append("classes", ObjectUtils.nullSafeToString(this.classes))//
.append("activeProfiles", ObjectUtils.nullSafeToString(this.activeProfiles))//
.append("testClass", testClass)//
.append("locations", ObjectUtils.nullSafeToString(locations))//
.append("classes", ObjectUtils.nullSafeToString(classes))//
.append("activeProfiles", ObjectUtils.nullSafeToString(activeProfiles))//
.append("contextLoader", nullSafeToString(contextLoader))//
.append("contextKey", this.contextKey)//
.append("contextKey", contextKey)//
.toString();
}
......
......@@ -37,7 +37,8 @@ import org.springframework.context.ApplicationContext;
* {@link #processContextConfiguration(ContextConfigurationAttributes) processContextConfiguration()}
* should be merged for all classes in the hierarchy of the root test class and
* then supplied to {@link #loadContext(MergedContextConfiguration) loadContext()}.
* Even though <code>SmartContextLoader</code> extends <code>ContextLoader</code>,
*
* <p>Even though <code>SmartContextLoader</code> extends <code>ContextLoader</code>,
* clients should favor <code>SmartContextLoader</code>-specific methods over those
* defined in <code>ContextLoader</code>, particularly because a
* <code>SmartContextLoader</code> may choose not to support methods defined in
......@@ -63,9 +64,8 @@ public interface SmartContextLoader extends ContextLoader {
/**
* Determines if this <code>SmartContextLoader</code> generates default resource
* locations or
* {@link org.springframework.context.annotation.Configuration configuration classes}
* if the <code>locations</code> or <code>classes</code>
* locations or {@link org.springframework.context.annotation.Configuration
* configuration classes} if the <code>locations</code> or <code>classes</code>
* present in the {@link ContextConfigurationAttributes} provided to
* {@link #processContextConfiguration()} are <code>null</code> or empty.
* <p>Returning a value of <code>true</code> signals not only that this
......
......@@ -66,34 +66,50 @@ public class DelegatingSmartContextLoader implements SmartContextLoader {
final boolean originallyHadResources = configAttributes.hasResources();
for (SmartContextLoader loader : candidates) {
if (logger.isDebugEnabled()) {
logger.debug(String.format("Potentially delegating to %s to process context configuration [%s].",
loader.getClass().getName(), configAttributes));
}
// If the original locations and classes were not empty, there's no
// need to bother with default generation checks; just let each
// loader process the configuration.
if (originallyHadResources) {
// If the original locations and classes were not empty, there's no
// need to bother with default generation checks; just let each
// loader process the configuration.
if (originallyHadResources) {
for (SmartContextLoader loader : candidates) {
if (logger.isDebugEnabled()) {
logger.debug(String.format("Delegating to %s to process context configuration [%s].",
loader.getClass().getName(), configAttributes));
}
loader.processContextConfiguration(configAttributes);
}
// Otherwise, if the loader claims to generate defaults, let it
// process the configuration.
else if (loader.generatesDefaults()) {
loader.processContextConfiguration(configAttributes);
if (configAttributes.hasResources() && logger.isInfoEnabled()) {
logger.info(String.format("SmartContextLoader candidate %s "
+ "generated defaults for context configuration [%s].", loader, configAttributes));
}
else if (generatesDefaults()) {
for (SmartContextLoader loader : candidates) {
boolean defaultResourcesAlreadyGenerated = configAttributes.hasResources();
// If defaults haven't already been generated and the loader
// claims to generate defaults, let it process the
// configuration.
if (!defaultResourcesAlreadyGenerated && loader.generatesDefaults()) {
if (logger.isDebugEnabled()) {
logger.debug(String.format(
"Delegating to %s to generate defaults for context configuration [%s].",
loader.getClass().getName(), configAttributes));
}
loader.processContextConfiguration(configAttributes);
if (configAttributes.hasResources()) {
if (logger.isInfoEnabled()) {
logger.info(String.format("SmartContextLoader candidate %s "
+ "generated defaults for context configuration [%s].", loader, configAttributes));
}
}
}
}
}
// If any loader claims to generate defaults but none actually did,
// throw an exception.
if (generatesDefaults() && !originallyHadResources && !configAttributes.hasResources()) {
throw new IllegalStateException(String.format("None of the SmartContextLoader candidates %s "
+ "was able to generate defaults for context configuration [%s].", candidates, configAttributes));
// If any loader claims to generate defaults but none actually did,
// throw an exception.
if (!configAttributes.hasResources()) {
throw new IllegalStateException(
String.format("None of the SmartContextLoader candidates %s "
+ "was able to generate defaults for context configuration [%s].", candidates,
configAttributes));
}
}
}
......
......@@ -16,11 +16,21 @@
package org.springframework.test.context.support;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.ContextConfigurationAttributes;
import org.springframework.test.context.ContextLoader;
import org.springframework.test.context.MergedContextConfiguration;
import org.springframework.util.ObjectUtils;
/**
* Unit tests for {@link DelegatingSmartContextLoader}.
......@@ -36,6 +46,10 @@ public class DelegatingSmartContextLoaderTests {
private final DelegatingSmartContextLoader loader = new DelegatingSmartContextLoader();
private static void assertEmpty(Object[] array) {
assertTrue(ObjectUtils.isEmpty(array));
}
// --- SmartContextLoader --------------------------------------------------
@Test
......@@ -43,9 +57,49 @@ public class DelegatingSmartContextLoaderTests {
assertTrue(loader.generatesDefaults());
}
@Test(expected = IllegalStateException.class)
public void processContextConfigurationWithoutLocationsAndConfigurationClassesForBogusTestClass() {
ContextConfigurationAttributes configAttributes = new ContextConfigurationAttributes(getClass(),
EMPTY_STRING_ARRAY, EMPTY_CLASS_ARRAY, true, ContextLoader.class);
loader.processContextConfiguration(configAttributes);
}
@Test
public void processContextConfigurationWithDefaultXmlConfigGeneration() {
ContextConfigurationAttributes configAttributes = new ContextConfigurationAttributes(XmlTestCase.class,
EMPTY_STRING_ARRAY, EMPTY_CLASS_ARRAY, true, ContextLoader.class);
loader.processContextConfiguration(configAttributes);
assertEquals(1, configAttributes.getLocations().length);
assertEmpty(configAttributes.getClasses());
}
@Test
public void processContextConfigurationWithDefaultConfigurationClassGeneration() {
ContextConfigurationAttributes configAttributes = new ContextConfigurationAttributes(ConfigClassTestCase.class,
EMPTY_STRING_ARRAY, EMPTY_CLASS_ARRAY, true, ContextLoader.class);
loader.processContextConfiguration(configAttributes);
assertEquals(1, configAttributes.getClasses().length);
assertEmpty(configAttributes.getLocations());
}
@Test
public void processContextConfigurationWithLocation() {
String[] locations = new String[] { "classpath:/foo.xml" };
ContextConfigurationAttributes configAttributes = new ContextConfigurationAttributes(getClass(), locations,
EMPTY_CLASS_ARRAY, true, ContextLoader.class);
loader.processContextConfiguration(configAttributes);
assertArrayEquals(locations, configAttributes.getLocations());
assertEmpty(configAttributes.getClasses());
}
@Test
public void processContextConfiguration() {
// TODO test processContextConfiguration().
public void processContextConfigurationWithConfigurationClass() {
Class<?>[] classes = new Class<?>[] { getClass() };
ContextConfigurationAttributes configAttributes = new ContextConfigurationAttributes(getClass(),
EMPTY_STRING_ARRAY, classes, true, ContextLoader.class);
loader.processContextConfiguration(configAttributes);
assertArrayEquals(classes, configAttributes.getClasses());
assertEmpty(configAttributes.getLocations());
}
@Test(expected = IllegalArgumentException.class)
......@@ -95,9 +149,29 @@ public class DelegatingSmartContextLoaderTests {
loader.loadContext(mergedConfig);
}
private void assertApplicationContextLoadsAndContainsFooString(MergedContextConfiguration mergedConfig)
throws Exception {
ApplicationContext applicationContext = loader.loadContext(mergedConfig);
assertNotNull(applicationContext);
assertEquals("foo", applicationContext.getBean(String.class));
assertTrue(applicationContext instanceof ConfigurableApplicationContext);
((ConfigurableApplicationContext) applicationContext).close();
}
@Test
public void loadContext() {
// TODO test loadContext().
public void loadContextWithXmlConfig() throws Exception {
MergedContextConfiguration mergedConfig = new MergedContextConfiguration(
XmlTestCase.class,
new String[] { "classpath:/org/springframework/test/context/support/DelegatingSmartContextLoaderTests$XmlTestCase-context.xml" },
EMPTY_CLASS_ARRAY, EMPTY_STRING_ARRAY, loader);
assertApplicationContextLoadsAndContainsFooString(mergedConfig);
}
@Test
public void loadContextWithConfigurationClass() throws Exception {
MergedContextConfiguration mergedConfig = new MergedContextConfiguration(ConfigClassTestCase.class,
EMPTY_STRING_ARRAY, new Class<?>[] { ConfigClassTestCase.Config.class }, EMPTY_STRING_ARRAY, loader);
assertApplicationContextLoadsAndContainsFooString(mergedConfig);
}
// --- ContextLoader -------------------------------------------------------
......@@ -112,4 +186,20 @@ public class DelegatingSmartContextLoaderTests {
loader.loadContext(EMPTY_STRING_ARRAY);
}
static class XmlTestCase {
}
static class ConfigClassTestCase {
@Configuration
static class Config {
@Bean
public String foo() {
return new String("foo");
}
}
}
}
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:c="http://www.springframework.org/schema/c"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd">
<bean id="foo" class="java.lang.String" c:_="foo" />
</beans>
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册