diff --git a/spring-test/src/main/java/org/springframework/test/context/BootstrapContext.java b/spring-test/src/main/java/org/springframework/test/context/BootstrapContext.java index fa12a797e3..13c311fa79 100644 --- a/spring-test/src/main/java/org/springframework/test/context/BootstrapContext.java +++ b/spring-test/src/main/java/org/springframework/test/context/BootstrapContext.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2014 the original author or authors. + * Copyright 2002-2015 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. @@ -28,7 +28,7 @@ package org.springframework.test.context; public interface BootstrapContext { /** - * Get the {@link Class test class} for this bootstrap context. + * Get the {@linkplain Class test class} for this bootstrap context. * @return the test class (never {@code null}) */ Class> getTestClass(); diff --git a/spring-test/src/main/java/org/springframework/test/context/TestContextBootstrapper.java b/spring-test/src/main/java/org/springframework/test/context/TestContextBootstrapper.java index 7252657f42..ae81c9ec4a 100644 --- a/spring-test/src/main/java/org/springframework/test/context/TestContextBootstrapper.java +++ b/spring-test/src/main/java/org/springframework/test/context/TestContextBootstrapper.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2014 the original author or authors. + * Copyright 2002-2015 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. @@ -29,15 +29,14 @@ import java.util.List; * *
The {@link TestContextManager} uses a {@code TestContextBootstrapper} to * {@linkplain #getTestExecutionListeners get the TestExecutionListeners} for the - * current test and to {@linkplain #buildMergedContextConfiguration build the - * merged context configuration} necessary to create the {@link TestContext} that + * current test and to {@linkplain #buildTestContext build the TestContext} that * it manages. * *
Concrete implementations must provide a {@code public} no-args constructor. * - *
Note: this SPI might potentially change in the future in + *
WARNING: this SPI will likely change in the future in * order to accommodate new requirements. Implementers are therefore strongly encouraged - * not to implement this interface directly but rather to extend + * not to implement this interface directly but rather to extend * {@link org.springframework.test.context.support.AbstractTestContextBootstrapper * AbstractTestContextBootstrapper} or one of its concrete subclasses instead. * @@ -59,28 +58,13 @@ public interface TestContextBootstrapper { BootstrapContext getBootstrapContext(); /** - * Get a list of newly instantiated {@link TestExecutionListener TestExecutionListeners} - * for the test class in the {@link BootstrapContext} associated with this bootstrapper. - *
If {@link TestExecutionListeners @TestExecutionListeners} is not - * present on the test class in the {@code BootstrapContext}, - * default listeners should be returned. Furthermore, default - * listeners must be sorted using - * {@link org.springframework.core.annotation.AnnotationAwareOrderComparator - * AnnotationAwareOrderComparator}. - *
Concrete implementations are free to determine what comprises the - * set of default listeners. However, by default, the Spring TestContext - * Framework will use the - * {@link org.springframework.core.io.support.SpringFactoriesLoader SpringFactoriesLoader} - * mechanism to look up all {@code TestExecutionListener} class names - * configured in all {@code META-INF/spring.factories} files on the classpath. - *
The {@link TestExecutionListeners#inheritListeners() inheritListeners}
- * flag of {@link TestExecutionListeners @TestExecutionListeners} must be
- * taken into consideration. Specifically, if the {@code inheritListeners}
- * flag is set to {@code true}, listeners declared for a given test class must
- * be appended to the end of the list of listeners declared in superclasses.
- * @return a list of {@code TestExecutionListener} instances
+ * Build the {@link TestContext} for the {@link BootstrapContext}
+ * associated with this bootstrapper.
+ * @return a new {@link TestContext}, never {@code null}
+ * @since 4.2
+ * @see #buildMergedContextConfiguration()
*/
- List Consult the Javadoc for the aforementioned annotations for details on
* the required semantics.
+ * Note that the implementation of {@link #buildTestContext()} should
+ * typically delegate to this method when constructing the {@code TestContext}.
* When determining which {@link ContextLoader} to use for a given test
* class, the following algorithm should be used:
* If {@link TestExecutionListeners @TestExecutionListeners} is not
+ * present on the test class in the {@code BootstrapContext},
+ * default listeners should be returned. Furthermore, default
+ * listeners must be sorted using
+ * {@link org.springframework.core.annotation.AnnotationAwareOrderComparator
+ * AnnotationAwareOrderComparator}.
+ * Concrete implementations are free to determine what comprises the
+ * set of default listeners. However, by default, the Spring TestContext
+ * Framework will use the
+ * {@link org.springframework.core.io.support.SpringFactoriesLoader SpringFactoriesLoader}
+ * mechanism to look up all {@code TestExecutionListener} class names
+ * configured in all {@code META-INF/spring.factories} files on the classpath.
+ * The {@link TestExecutionListeners#inheritListeners() inheritListeners}
+ * flag of {@link TestExecutionListeners @TestExecutionListeners} must be
+ * taken into consideration. Specifically, if the {@code inheritListeners}
+ * flag is set to {@code true}, listeners declared for a given test class must
+ * be appended to the end of the list of listeners declared in superclasses.
+ * @return a list of {@code TestExecutionListener} instances
+ */
+ List Specifically, a {@code TestContextManager} is responsible for managing a
* single {@link TestContext} and signaling events to all registered
- * {@link TestExecutionListener TestExecutionListeners} at well defined test
+ * {@link TestExecutionListener TestExecutionListeners} at the following test
* execution points:
*
* Support for loading and accessing
+ * {@link org.springframework.context.ApplicationContext application contexts},
+ * dependency injection of test instances,
+ * {@link org.springframework.transaction.annotation.Transactional transactional}
+ * execution of test methods, etc. is provided by
+ * {@link SmartContextLoader ContextLoaders} and {@link TestExecutionListener
+ * TestExecutionListeners}, which are configured via
+ * {@link ContextConfiguration @ContextConfiguration} and
+ * {@link TestExecutionListeners @TestExecutionListeners}.
+ *
+ * Bootstrapping of the {@code TestContext}, the default {@code ContextLoader},
+ * default {@code TestExecutionListeners}, and their collaborators is performed
+ * by a {@link TestContextBootstrapper}, which is configured via
+ * {@link BootstrapWith @BootstrapWith}.
+ *
* @author Sam Brannen
* @author Juergen Hoeller
* @since 2.5
@@ -90,7 +101,7 @@ public class TestContextManager {
CacheAwareContextLoaderDelegate cacheAwareContextLoaderDelegate = new DefaultCacheAwareContextLoaderDelegate();
BootstrapContext bootstrapContext = new DefaultBootstrapContext(testClass, cacheAwareContextLoaderDelegate);
TestContextBootstrapper testContextBootstrapper = BootstrapUtils.resolveTestContextBootstrapper(bootstrapContext);
- this.testContext = new DefaultTestContext(testContextBootstrapper);
+ this.testContext = testContextBootstrapper.buildTestContext();
registerTestExecutionListeners(testContextBootstrapper.getTestExecutionListeners());
}
@@ -190,7 +201,7 @@ public class TestContextManager {
* @see #getTestExecutionListeners()
*/
public void prepareTestInstance(Object testInstance) throws Exception {
- Assert.notNull(testInstance, "testInstance must not be null");
+ Assert.notNull(testInstance, "Test instance must not be null");
if (logger.isTraceEnabled()) {
logger.trace("prepareTestInstance(): instance [" + testInstance + "]");
}
@@ -271,7 +282,7 @@ public class TestContextManager {
* @see #getTestExecutionListeners()
*/
public void afterTestMethod(Object testInstance, Method testMethod, Throwable exception) throws Exception {
- Assert.notNull(testInstance, "testInstance must not be null");
+ Assert.notNull(testInstance, "Test instance must not be null");
if (logger.isTraceEnabled()) {
logger.trace("afterTestMethod(): instance [" + testInstance + "], method [" + testMethod +
"], exception [" + exception + "]");
diff --git a/spring-test/src/main/java/org/springframework/test/context/support/AbstractTestContextBootstrapper.java b/spring-test/src/main/java/org/springframework/test/context/support/AbstractTestContextBootstrapper.java
index 709c82e972..d538777e57 100644
--- a/spring-test/src/main/java/org/springframework/test/context/support/AbstractTestContextBootstrapper.java
+++ b/spring-test/src/main/java/org/springframework/test/context/support/AbstractTestContextBootstrapper.java
@@ -44,6 +44,7 @@ import org.springframework.test.context.ContextHierarchy;
import org.springframework.test.context.ContextLoader;
import org.springframework.test.context.MergedContextConfiguration;
import org.springframework.test.context.SmartContextLoader;
+import org.springframework.test.context.TestContext;
import org.springframework.test.context.TestContextBootstrapper;
import org.springframework.test.context.TestExecutionListener;
import org.springframework.test.context.TestExecutionListeners;
@@ -93,6 +94,21 @@ public abstract class AbstractTestContextBootstrapper implements TestContextBoot
return this.bootstrapContext;
}
+ /**
+ * Build a new {@link DefaultTestContext} using the {@linkplain Class test class}
+ * and {@link CacheAwareContextLoaderDelegate} in the {@link BootstrapContext}
+ * associated with this bootstrapper and by delegating to
+ * {@link #buildMergedContextConfiguration()}.
+ * Concrete subclasses may choose to override this method to return a
+ * custom {@link TestContext} implementation.
+ * @since 4.2
+ */
+ @Override
+ public TestContext buildTestContext() {
+ return new DefaultTestContext(bootstrapContext.getTestClass(), buildMergedContextConfiguration(),
+ bootstrapContext.getCacheAwareContextLoaderDelegate());
+ }
+
/**
* {@inheritDoc}
*/
diff --git a/spring-test/src/main/java/org/springframework/test/context/DefaultTestContext.java b/spring-test/src/main/java/org/springframework/test/context/support/DefaultTestContext.java
similarity index 55%
rename from spring-test/src/main/java/org/springframework/test/context/DefaultTestContext.java
rename to spring-test/src/main/java/org/springframework/test/context/support/DefaultTestContext.java
index eac358e8e5..bd730b3254 100644
--- a/spring-test/src/main/java/org/springframework/test/context/DefaultTestContext.java
+++ b/spring-test/src/main/java/org/springframework/test/context/support/DefaultTestContext.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2014 the original author or authors.
+ * Copyright 2002-2015 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.
@@ -14,7 +14,7 @@
* limitations under the License.
*/
-package org.springframework.test.context;
+package org.springframework.test.context.support;
import java.lang.reflect.Method;
@@ -22,21 +22,19 @@ import org.springframework.context.ApplicationContext;
import org.springframework.core.AttributeAccessorSupport;
import org.springframework.core.style.ToStringCreator;
import org.springframework.test.annotation.DirtiesContext.HierarchyMode;
+import org.springframework.test.context.CacheAwareContextLoaderDelegate;
+import org.springframework.test.context.MergedContextConfiguration;
+import org.springframework.test.context.TestContext;
import org.springframework.util.Assert;
/**
* Default implementation of the {@link TestContext} interface.
*
- * Although {@code DefaultTestContext} was first introduced in Spring Framework
- * 4.0, the initial implementation of this class was extracted from the existing
- * code base for {@code TestContext} when {@code TestContext} was converted into
- * an interface.
- *
* @author Sam Brannen
* @author Juergen Hoeller
* @since 4.0
*/
-class DefaultTestContext extends AttributeAccessorSupport implements TestContext {
+public class DefaultTestContext extends AttributeAccessorSupport implements TestContext {
private static final long serialVersionUID = -5827157174866681233L;
@@ -54,24 +52,42 @@ class DefaultTestContext extends AttributeAccessorSupport implements TestContext
/**
- * Construct a new test context using the supplied {@link TestContextBootstrapper}.
- * @param testContextBootstrapper the {@code TestContextBootstrapper} to use
- * to construct the test context (must not be {@code null})
+ * Construct a new {@code DefaultTestContext} from the supplied arguments.
+ * @param testClass the test class for this test context; never {@code null}
+ * @param mergedContextConfiguration the merged application context
+ * configuration for this test context; never {@code null}
+ * @param cacheAwareContextLoaderDelegate the delegate to use for loading
+ * and closing the application context for this test context; never {@code null}
*/
- DefaultTestContext(TestContextBootstrapper testContextBootstrapper) {
- Assert.notNull(testContextBootstrapper, "TestContextBootstrapper must not be null");
-
- BootstrapContext bootstrapContext = testContextBootstrapper.getBootstrapContext();
- this.testClass = bootstrapContext.getTestClass();
- this.cacheAwareContextLoaderDelegate = bootstrapContext.getCacheAwareContextLoaderDelegate();
- this.mergedContextConfiguration = testContextBootstrapper.buildMergedContextConfiguration();
+ public DefaultTestContext(Class> testClass, MergedContextConfiguration mergedContextConfiguration,
+ CacheAwareContextLoaderDelegate cacheAwareContextLoaderDelegate) {
+ Assert.notNull(testClass, "testClass must not be null");
+ Assert.notNull(mergedContextConfiguration, "MergedContextConfiguration must not be null");
+ Assert.notNull(cacheAwareContextLoaderDelegate, "CacheAwareContextLoaderDelegate must not be null");
+ this.testClass = testClass;
+ this.mergedContextConfiguration = mergedContextConfiguration;
+ this.cacheAwareContextLoaderDelegate = cacheAwareContextLoaderDelegate;
}
-
+ /**
+ * Get the {@linkplain ApplicationContext application context} for this
+ * test context.
+ * The default implementation delegates to the {@link CacheAwareContextLoaderDelegate}
+ * that was supplied when this {@code TestContext} was constructed.
+ * @see CacheAwareContextLoaderDelegate#loadContext
+ */
public ApplicationContext getApplicationContext() {
return this.cacheAwareContextLoaderDelegate.loadContext(this.mergedContextConfiguration);
}
+ /**
+ * Mark the {@linkplain ApplicationContext application context} associated
+ * with this test context as dirty (i.e., by removing it from the
+ * context cache and closing it).
+ * The default implementation delegates to the {@link CacheAwareContextLoaderDelegate}
+ * that was supplied when this {@code TestContext} was constructed.
+ * @see CacheAwareContextLoaderDelegate#closeContext
+ */
public void markApplicationContextDirty(HierarchyMode hierarchyMode) {
this.cacheAwareContextLoaderDelegate.closeContext(this.mergedContextConfiguration, hierarchyMode);
}
diff --git a/spring-test/src/test/java/org/springframework/test/context/TestContextTestUtils.java b/spring-test/src/test/java/org/springframework/test/context/TestContextTestUtils.java
index 3f1eb86edf..da43525bc0 100644
--- a/spring-test/src/test/java/org/springframework/test/context/TestContextTestUtils.java
+++ b/spring-test/src/test/java/org/springframework/test/context/TestContextTestUtils.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2002-2014 the original author or authors.
+ * Copyright 2002-2015 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.
@@ -28,12 +28,12 @@ public abstract class TestContextTestUtils {
return buildTestContext(testClass, new DefaultCacheAwareContextLoaderDelegate(contextCache));
}
- public static TestContext buildTestContext(
- Class> testClass, CacheAwareContextLoaderDelegate cacheAwareContextLoaderDelegate) {
+ public static TestContext buildTestContext(Class> testClass,
+ CacheAwareContextLoaderDelegate cacheAwareContextLoaderDelegate) {
BootstrapContext bootstrapContext = new DefaultBootstrapContext(testClass, cacheAwareContextLoaderDelegate);
TestContextBootstrapper testContextBootstrapper = BootstrapUtils.resolveTestContextBootstrapper(bootstrapContext);
- return new DefaultTestContext(testContextBootstrapper);
+ return testContextBootstrapper.buildTestContext();
}
}
@@ -106,7 +93,32 @@ public interface TestContextBootstrapper {
* {@code ContextLoader} class to use as as default.
*
* @return the merged context configuration, never {@code null}
+ * @see #buildTestContext()
*/
MergedContextConfiguration buildMergedContextConfiguration();
+ /**
+ * Get a list of newly instantiated {@link TestExecutionListener TestExecutionListeners}
+ * for the test class in the {@link BootstrapContext} associated with this bootstrapper.
+ *
@@ -56,6 +52,21 @@ import org.springframework.util.Assert;
* 4's {@link org.junit.AfterClass @AfterClass})
*
*
+ *