[SPR-5640] Added support for marking the test application context as 'dirty' after each test method within a given test class via the new DirtiesContext.classMode() attribute.

This commit is contained in:
Sam Brannen
2009-07-06 19:17:16 +00:00
parent ea2580af68
commit c254f389c0
3 changed files with 157 additions and 43 deletions

View File

@@ -27,8 +27,12 @@ import java.lang.annotation.Target;
* {@link org.springframework.context.ApplicationContext ApplicationContext}
* associated with a test is <em>dirty</em> and should be closed:
* <ul>
* <li>after the current test, when declared at the method level, or</li>
* <li>after the current test class, when declared at the class level.</li>
* <li>after the current test, when declared at the method level</li>
* <li>after each test method in the current test class, when declared at the
* class level with class mode set to {@link ClassMode#AFTER_EACH_TEST_METHOD
* AFTER_EACH_TEST_METHOD}</li>
* <li>after the current test class, when declared at the class level with class
* mode set to {@link ClassMode#AFTER_CLASS AFTER_CLASS}</li>
* </ul>
* <p>
* Use this annotation if a test has modified the context (for example, by
@@ -39,11 +43,14 @@ import java.lang.annotation.Target;
* <code>&#064;DirtiesContext</code> may be used as a class-level and
* method-level annotation within the same class. In such scenarios, the
* <code>ApplicationContext</code> will be marked as <em>dirty</em> after any
* such annotated method as well as after the entire class.
* such annotated method as well as after the entire class. If the
* {@link ClassMode} is set to {@link ClassMode#AFTER_EACH_TEST_METHOD
* AFTER_EACH_TEST_METHOD}, the context will be marked dirty after each test
* method in the class.
* </p>
*
* @author Rod Johnson
* @author Sam Brannen
* @author Rod Johnson
* @since 2.0
*/
@Target( { ElementType.TYPE, ElementType.METHOD })
@@ -51,4 +58,42 @@ import java.lang.annotation.Target;
@Documented
public @interface DirtiesContext {
/**
* Defines <i>modes</i> which determine how
* <code>&#064;DirtiesContext</code> is interpreted when used to annotate a
* test class.
*
* @author Sam Brannen
* @since 3.0
*/
public static enum ClassMode {
/**
* The associated <code>ApplicationContext</code> will be marked as
* <em>dirty</em> after the test class.
*/
AFTER_CLASS,
/**
* The associated <code>ApplicationContext</code> will be marked as
* <em>dirty</em> after each test method in the class.
*/
AFTER_EACH_TEST_METHOD;
}
/**
* The <i>mode</i> to use when a test class is annotated with
* <code>&#064;DirtiesContext</code>.
* <p>
* Defaults to {@link ClassMode#AFTER_CLASS AFTER_CLASS}.
* </p>
* <p>
* Note: setting the class mode on an annotated test method has no meaning,
* since the mere presence of the <code>&#064;DirtiesContext</code>
* annotation on a test method is sufficient.
* </p>
*/
public ClassMode classMode() default ClassMode.AFTER_CLASS;
}

View File

@@ -22,13 +22,15 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.annotation.DirtiesContext.ClassMode;
import org.springframework.test.context.TestContext;
import org.springframework.util.Assert;
/**
* <code>TestExecutionListener</code> which processes test classes and test
* methods configured with the {@link DirtiesContext &#064;DirtiesContext}
* annotation.
* <code>TestExecutionListener</code> which provides support for marking the
* <code>ApplicationContext</code> associated with a test as <em>dirty</em> for
* both test classes and test methods configured with the {@link DirtiesContext
* &#064;DirtiesContext} annotation.
*
* @author Sam Brannen
* @author Juergen Hoeller
@@ -56,23 +58,37 @@ public class DirtiesContextTestExecutionListener extends AbstractTestExecutionLi
/**
* If the current test method of the supplied {@link TestContext test
* context} is annotated with {@link DirtiesContext &#064;DirtiesContext},
* the {@link ApplicationContext application context} of the test context
* will be {@link TestContext#markApplicationContextDirty() marked as dirty}
* , and the
* or if the test class is annotated with {@link DirtiesContext
* &#064;DirtiesContext} and the {@link DirtiesContext#classMode() class
* mode} is set to {@link ClassMode#AFTER_EACH_TEST_METHOD
* AFTER_EACH_TEST_METHOD}, the {@link ApplicationContext application
* context} of the test context will be
* {@link TestContext#markApplicationContextDirty() marked as dirty} and the
* {@link DependencyInjectionTestExecutionListener#REINJECT_DEPENDENCIES_ATTRIBUTE
* REINJECT_DEPENDENCIES_ATTRIBUTE} in the test context will be set to
* <code>true</code>.
*/
@Override
public void afterTestMethod(TestContext testContext) throws Exception {
Class<?> testClass = testContext.getTestClass();
Assert.notNull(testClass, "The test class of the supplied TestContext must not be null");
Method testMethod = testContext.getTestMethod();
Assert.notNull(testMethod, "The test method of the supplied TestContext must not be null");
boolean dirtiesContext = testMethod.isAnnotationPresent(DirtiesContext.class);
final Class<DirtiesContext> annotationType = DirtiesContext.class;
boolean methodDirtiesContext = testMethod.isAnnotationPresent(annotationType);
boolean classDirtiesContext = testClass.isAnnotationPresent(annotationType);
DirtiesContext classDirtiesContextAnnotation = testClass.getAnnotation(annotationType);
ClassMode classMode = classDirtiesContext ? classDirtiesContextAnnotation.classMode() : null;
if (logger.isDebugEnabled()) {
logger.debug("After test method: context [" + testContext + "], dirtiesContext [" + dirtiesContext + "].");
logger.debug("After test method: context [" + testContext + "], class-level dirtiesContext ["
+ classDirtiesContext + "], class mode [" + classMode + "], method-level dirtiesContext ["
+ methodDirtiesContext + "].");
}
if (dirtiesContext) {
if (methodDirtiesContext || (classDirtiesContext && classMode == ClassMode.AFTER_EACH_TEST_METHOD)) {
dirtyContext(testContext);
}
}