[SPR-5916] ContextLoader class is now inherited from class hierarchy if not specified explicitly via @ContextConfiguration's loader attribute on the current test class.
git-svn-id: https://src.springframework.org/svn/spring-framework/trunk@1561 50f2f4bb-b051-0410-bef5-90022cba6387
This commit is contained in:
parent
b8811bb720
commit
2d1d61cb0f
|
|
@ -87,6 +87,10 @@ public @interface ContextConfiguration {
|
||||||
/**
|
/**
|
||||||
* The type of {@link ContextLoader} to use for loading an
|
* The type of {@link ContextLoader} to use for loading an
|
||||||
* {@link org.springframework.context.ApplicationContext ApplicationContext}.
|
* {@link org.springframework.context.ApplicationContext ApplicationContext}.
|
||||||
|
* <p>If not specified, the loader will be inherited from the first superclass
|
||||||
|
* which is annotated with <code>@ContextConfiguration</code> and specifies
|
||||||
|
* an explicit loader. If no class in the hierarchy specifies an explicit
|
||||||
|
* loader, a default loader will be used instead.
|
||||||
*/
|
*/
|
||||||
Class<? extends ContextLoader> loader() default ContextLoader.class;
|
Class<? extends ContextLoader> loader() default ContextLoader.class;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2008 the original author or authors.
|
* Copyright 2002-2009 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -95,7 +95,6 @@ public class TestContext extends AttributeAccessorSupport {
|
||||||
* @param defaultContextLoaderClassName the name of the default
|
* @param defaultContextLoaderClassName the name of the default
|
||||||
* <code>ContextLoader</code> class to use (may be <code>null</code>)
|
* <code>ContextLoader</code> class to use (may be <code>null</code>)
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
TestContext(Class<?> testClass, ContextCache contextCache, String defaultContextLoaderClassName) {
|
TestContext(Class<?> testClass, ContextCache contextCache, String defaultContextLoaderClassName) {
|
||||||
Assert.notNull(testClass, "Test class must not be null");
|
Assert.notNull(testClass, "Test class must not be null");
|
||||||
Assert.notNull(contextCache, "ContextCache must not be null");
|
Assert.notNull(contextCache, "ContextCache must not be null");
|
||||||
|
|
@ -119,23 +118,8 @@ public class TestContext extends AttributeAccessorSupport {
|
||||||
+ "]");
|
+ "]");
|
||||||
}
|
}
|
||||||
|
|
||||||
Class<? extends ContextLoader> contextLoaderClass = contextConfiguration.loader();
|
Class<? extends ContextLoader> contextLoaderClass = retrieveContextLoaderClass(testClass,
|
||||||
if (ContextLoader.class.equals(contextLoaderClass)) {
|
defaultContextLoaderClassName);
|
||||||
try {
|
|
||||||
if (logger.isTraceEnabled()) {
|
|
||||||
logger.trace("Using default ContextLoader class [" + defaultContextLoaderClassName
|
|
||||||
+ "] for @ContextConfiguration [" + contextConfiguration + "] and class [" + testClass
|
|
||||||
+ "]");
|
|
||||||
}
|
|
||||||
contextLoaderClass = (Class<? extends ContextLoader>) getClass().getClassLoader().loadClass(
|
|
||||||
defaultContextLoaderClassName);
|
|
||||||
}
|
|
||||||
catch (ClassNotFoundException ex) {
|
|
||||||
throw new IllegalStateException("Could not load default ContextLoader class ["
|
|
||||||
+ defaultContextLoaderClassName + "]. Specify @ContextConfiguration's 'loader' "
|
|
||||||
+ "attribute or make the default loader class available.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
contextLoader = (ContextLoader) BeanUtils.instantiateClass(contextLoaderClass);
|
contextLoader = (ContextLoader) BeanUtils.instantiateClass(contextLoaderClass);
|
||||||
locations = retrieveContextLocations(contextLoader, testClass);
|
locations = retrieveContextLocations(contextLoader, testClass);
|
||||||
}
|
}
|
||||||
|
|
@ -146,6 +130,80 @@ public class TestContext extends AttributeAccessorSupport {
|
||||||
this.locations = locations;
|
this.locations = locations;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* Retrieve the {@link ContextLoader} {@link Class} to use for the supplied
|
||||||
|
* {@link Class test class}.
|
||||||
|
* <ol>
|
||||||
|
* <li>If the {@link ContextConfiguration#loader() loader} attribute of
|
||||||
|
* {@link ContextConfiguration @ContextConfiguration} is configured
|
||||||
|
* with an explicit class, that class will be returned.</li>
|
||||||
|
* <li>If a <code>loader</code> class is not specified, the class hierarchy
|
||||||
|
* will be traversed to find a parent class annotated with
|
||||||
|
* <code>@ContextConfiguration</code>; go to step #1.</li>
|
||||||
|
* </ol>
|
||||||
|
* <p>
|
||||||
|
* If no explicit <code>loader</code> class is found after traversing the
|
||||||
|
* class hierarchy, an attempt will be made to load and return the class
|
||||||
|
* with the supplied <code>defaultContextLoaderClassName</code>.
|
||||||
|
*
|
||||||
|
* @param clazz the class for which to retrieve <code>ContextLoader</code>
|
||||||
|
* class; must not be <code>null</code>
|
||||||
|
* @param defaultContextLoaderClassName the name of the default
|
||||||
|
* <code>ContextLoader</code> class to use; must not be <code>null</code> or
|
||||||
|
* empty
|
||||||
|
* @return the <code>ContextLoader</code> class to use for the specified
|
||||||
|
* class
|
||||||
|
* @throws IllegalArgumentException if {@link ContextConfiguration
|
||||||
|
* @ContextConfiguration} is not <em>present</em> on the supplied class
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private Class<? extends ContextLoader> retrieveContextLoaderClass(Class<?> clazz,
|
||||||
|
String defaultContextLoaderClassName) {
|
||||||
|
Assert.notNull(clazz, "Class must not be null");
|
||||||
|
Assert.hasText(defaultContextLoaderClassName, "Default ContextLoader class name must not be null or empty");
|
||||||
|
|
||||||
|
Class<ContextConfiguration> annotationType = ContextConfiguration.class;
|
||||||
|
Class<?> declaringClass = AnnotationUtils.findAnnotationDeclaringClass(annotationType, clazz);
|
||||||
|
Assert.notNull(declaringClass, "Could not find an 'annotation declaring class' for annotation type ["
|
||||||
|
+ annotationType + "] and class [" + clazz + "]");
|
||||||
|
|
||||||
|
while (declaringClass != null) {
|
||||||
|
ContextConfiguration contextConfiguration = declaringClass.getAnnotation(annotationType);
|
||||||
|
if (logger.isTraceEnabled()) {
|
||||||
|
logger.trace("Processing ContextLoader for @ContextConfiguration [" + contextConfiguration
|
||||||
|
+ "] and declaring class [" + declaringClass + "]");
|
||||||
|
}
|
||||||
|
|
||||||
|
Class<? extends ContextLoader> contextLoaderClass = contextConfiguration.loader();
|
||||||
|
if (!ContextLoader.class.equals(contextLoaderClass)) {
|
||||||
|
if (logger.isDebugEnabled()) {
|
||||||
|
logger.debug("Found explicit ContextLoader [" + contextLoaderClass
|
||||||
|
+ "] for @ContextConfiguration [" + contextConfiguration + "] and declaring class ["
|
||||||
|
+ declaringClass + "]");
|
||||||
|
}
|
||||||
|
return contextLoaderClass;
|
||||||
|
}
|
||||||
|
|
||||||
|
declaringClass = AnnotationUtils.findAnnotationDeclaringClass(annotationType,
|
||||||
|
declaringClass.getSuperclass());
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
ContextConfiguration contextConfiguration = clazz.getAnnotation(ContextConfiguration.class);
|
||||||
|
if (logger.isTraceEnabled()) {
|
||||||
|
logger.trace("Using default ContextLoader class [" + defaultContextLoaderClassName
|
||||||
|
+ "] for @ContextConfiguration [" + contextConfiguration + "] and class [" + clazz + "]");
|
||||||
|
}
|
||||||
|
return (Class<? extends ContextLoader>) getClass().getClassLoader().loadClass(defaultContextLoaderClassName);
|
||||||
|
}
|
||||||
|
catch (ClassNotFoundException ex) {
|
||||||
|
throw new IllegalStateException("Could not load default ContextLoader class ["
|
||||||
|
+ defaultContextLoaderClassName + "]. Specify @ContextConfiguration's 'loader' "
|
||||||
|
+ "attribute or make the default loader class available.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve {@link ApplicationContext} resource locations for the supplied
|
* Retrieve {@link ApplicationContext} resource locations for the supplied
|
||||||
* {@link Class class}, using the supplied {@link ContextLoader} to
|
* {@link Class class}, using the supplied {@link ContextLoader} to
|
||||||
|
|
@ -157,10 +215,10 @@ public class TestContext extends AttributeAccessorSupport {
|
||||||
* @ContextConfiguration} will be taken into consideration.
|
* @ContextConfiguration} will be taken into consideration.
|
||||||
* Specifically, if the <code>inheritLocations</code> flag is set to
|
* Specifically, if the <code>inheritLocations</code> flag is set to
|
||||||
* <code>true</code>, locations defined in the annotated class will be
|
* <code>true</code>, locations defined in the annotated class will be
|
||||||
* appended to the locations defined in superclasses. @param
|
* appended to the locations defined in superclasses.
|
||||||
* contextLoader the ContextLoader to use for processing the locations (must
|
|
||||||
* not be <code>null</code>)
|
|
||||||
*
|
*
|
||||||
|
* @param contextLoader the ContextLoader to use for processing the
|
||||||
|
* locations (must not be <code>null</code>)
|
||||||
* @param clazz the class for which to retrieve the resource locations (must
|
* @param clazz the class for which to retrieve the resource locations (must
|
||||||
* not be <code>null</code>)
|
* not be <code>null</code>)
|
||||||
* @return the list of ApplicationContext resource locations for the
|
* @return the list of ApplicationContext resource locations for the
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
dog.(class)=org.springframework.beans.Pet
|
||||||
|
dog.$0=Fido
|
||||||
|
|
||||||
|
testString2.(class)=java.lang.String
|
||||||
|
testString2.$0=Test String #2
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2002-2009 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.configuration;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.springframework.beans.Pet;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.test.context.ContextConfiguration;
|
||||||
|
import org.springframework.test.context.ContextLoader;
|
||||||
|
import org.springframework.test.context.junit4.PropertiesBasedSpringJUnit4ClassRunnerAppCtxTests;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Integration tests which verify that the same custom {@link ContextLoader} can
|
||||||
|
* be used at all levels within a test class hierarchy when the
|
||||||
|
* <code>loader</code> is <i>inherited</i> (i.e., not explicitly declared) via
|
||||||
|
* {@link ContextConfiguration @ContextConfiguration}.
|
||||||
|
*
|
||||||
|
* @author Sam Brannen
|
||||||
|
* @since 3.0
|
||||||
|
* @see PropertiesBasedSpringJUnit4ClassRunnerAppCtxTests
|
||||||
|
* @see ContextConfigurationWithPropertiesExtendingPropertiesTests
|
||||||
|
*/
|
||||||
|
@ContextConfiguration
|
||||||
|
public class ContextConfigurationWithPropertiesExtendingPropertiesAndInheritedLoaderTests extends
|
||||||
|
PropertiesBasedSpringJUnit4ClassRunnerAppCtxTests {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private Pet dog;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private String testString2;
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void verifyExtendedAnnotationAutowiredFields() {
|
||||||
|
assertNotNull("The dog field should have been autowired.", this.dog);
|
||||||
|
assertEquals("Fido", this.dog.getName());
|
||||||
|
|
||||||
|
assertNotNull("The testString2 field should have been autowired.", this.testString2);
|
||||||
|
assertEquals("Test String #2", this.testString2);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,5 @@
|
||||||
|
dog.(class)=org.springframework.beans.Pet
|
||||||
|
dog.$0=Fido
|
||||||
|
|
||||||
|
testString2.(class)=java.lang.String
|
||||||
|
testString2.$0=Test String #2
|
||||||
|
|
@ -0,0 +1,61 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2002-2009 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.configuration;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertNotNull;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.springframework.beans.Pet;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.test.context.ContextConfiguration;
|
||||||
|
import org.springframework.test.context.ContextLoader;
|
||||||
|
import org.springframework.test.context.junit4.PropertiesBasedSpringJUnit4ClassRunnerAppCtxTests;
|
||||||
|
import org.springframework.test.context.support.GenericPropertiesContextLoader;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Integration tests which verify that the same custom {@link ContextLoader} can
|
||||||
|
* be used at all levels within a test class hierarchy when the
|
||||||
|
* <code>loader</code> is explicitly declared via {@link ContextConfiguration
|
||||||
|
* @ContextConfiguration}.
|
||||||
|
*
|
||||||
|
* @author Sam Brannen
|
||||||
|
* @since 3.0
|
||||||
|
* @see PropertiesBasedSpringJUnit4ClassRunnerAppCtxTests
|
||||||
|
* @see ContextConfigurationWithPropertiesExtendingPropertiesAndInheritedLoaderTests
|
||||||
|
*/
|
||||||
|
@ContextConfiguration(loader = GenericPropertiesContextLoader.class)
|
||||||
|
public class ContextConfigurationWithPropertiesExtendingPropertiesTests extends
|
||||||
|
PropertiesBasedSpringJUnit4ClassRunnerAppCtxTests {
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private Pet dog;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private String testString2;
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void verifyExtendedAnnotationAutowiredFields() {
|
||||||
|
assertNotNull("The dog field should have been autowired.", this.dog);
|
||||||
|
assertEquals("Fido", this.dog.getName());
|
||||||
|
|
||||||
|
assertNotNull("The testString2 field should have been autowired.", this.testString2);
|
||||||
|
assertEquals("Test String #2", this.testString2);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue