Browse Source

Introduce buildTestContext() in TestContextBootstrapper

This commit moves the responsibility of building a TestContext from the
TestContextManager to a TestContextBootstrapper.

In addition, DefaultTestContext is now a public class residing in the
"support" subpackage.

Issue: SPR-12683
pull/780/head
Sam Brannen 10 years ago
parent
commit
186abcb054
  1. 4
      spring-test/src/main/java/org/springframework/test/context/BootstrapContext.java
  2. 64
      spring-test/src/main/java/org/springframework/test/context/TestContextBootstrapper.java
  3. 29
      spring-test/src/main/java/org/springframework/test/context/TestContextManager.java
  4. 16
      spring-test/src/main/java/org/springframework/test/context/support/AbstractTestContextBootstrapper.java
  5. 54
      spring-test/src/main/java/org/springframework/test/context/support/DefaultTestContext.java
  6. 8
      spring-test/src/test/java/org/springframework/test/context/TestContextTestUtils.java

4
spring-test/src/main/java/org/springframework/test/context/BootstrapContext.java

@ -1,5 +1,5 @@ @@ -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; @@ -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();

64
spring-test/src/main/java/org/springframework/test/context/TestContextBootstrapper.java

@ -1,5 +1,5 @@ @@ -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; @@ -29,15 +29,14 @@ import java.util.List;
*
* <p>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.
*
* <p>Concrete implementations must provide a {@code public} no-args constructor.
*
* <p><strong>Note</strong>: this SPI might potentially change in the future in
* <p><strong>WARNING</strong>: this SPI will likely change in the future in
* order to accommodate new requirements. Implementers are therefore strongly encouraged
* <em>not</em> to implement this interface directly but rather to <em>extend</em>
* <strong>not</strong> to implement this interface directly but rather to <em>extend</em>
* {@link org.springframework.test.context.support.AbstractTestContextBootstrapper
* AbstractTestContextBootstrapper} or one of its concrete subclasses instead.
*
@ -59,28 +58,13 @@ public interface TestContextBootstrapper { @@ -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.
* <p>If {@link TestExecutionListeners @TestExecutionListeners} is not
* <em>present</em> on the test class in the {@code BootstrapContext},
* <em>default</em> listeners should be returned. Furthermore, default
* listeners must be sorted using
* {@link org.springframework.core.annotation.AnnotationAwareOrderComparator
* AnnotationAwareOrderComparator}.
* <p>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.
* <p>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<TestExecutionListener> getTestExecutionListeners();
TestContext buildTestContext();
/**
* Build the {@linkplain MergedContextConfiguration merged context configuration}
@ -94,9 +78,12 @@ public interface TestContextBootstrapper { @@ -94,9 +78,12 @@ public interface TestContextBootstrapper {
* <li>Active bean definition profiles declared via {@link ActiveProfiles @ActiveProfiles}</li>
* <li>{@linkplain org.springframework.context.ApplicationContextInitializer
* Context initializers} declared via {@link ContextConfiguration#initializers}</li>
* <li>Test property sources declared via {@link TestPropertySource @TestPropertySource}</li>
* </ul>
* <p>Consult the Javadoc for the aforementioned annotations for details on
* the required semantics.
* <p>Note that the implementation of {@link #buildTestContext()} should
* typically delegate to this method when constructing the {@code TestContext}.
* <p>When determining which {@link ContextLoader} to use for a given test
* class, the following algorithm should be used:
* <ol>
@ -106,7 +93,32 @@ public interface TestContextBootstrapper { @@ -106,7 +93,32 @@ public interface TestContextBootstrapper {
* {@code ContextLoader} class to use as as default.</li>
* </ol>
* @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.
* <p>If {@link TestExecutionListeners @TestExecutionListeners} is not
* <em>present</em> on the test class in the {@code BootstrapContext},
* <em>default</em> listeners should be returned. Furthermore, default
* listeners must be sorted using
* {@link org.springframework.core.annotation.AnnotationAwareOrderComparator
* AnnotationAwareOrderComparator}.
* <p>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.
* <p>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<TestExecutionListener> getTestExecutionListeners();
}

29
spring-test/src/main/java/org/springframework/test/context/TestContextManager.java

@ -28,15 +28,11 @@ import org.springframework.util.Assert; @@ -28,15 +28,11 @@ import org.springframework.util.Assert;
/**
* {@code TestContextManager} is the main entry point into the <em>Spring
* TestContext Framework</em>, which provides 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.
* TestContext Framework</em>.
*
* <p>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:
*
* <ul>
@ -56,6 +52,21 @@ import org.springframework.util.Assert; @@ -56,6 +52,21 @@ import org.springframework.util.Assert;
* 4's {@link org.junit.AfterClass @AfterClass})</li>
* </ul>
*
* <p>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}.
*
* <p>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 { @@ -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 { @@ -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 { @@ -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 + "]");

16
spring-test/src/main/java/org/springframework/test/context/support/AbstractTestContextBootstrapper.java

@ -44,6 +44,7 @@ import org.springframework.test.context.ContextHierarchy; @@ -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 @@ -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()}.
* <p>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}
*/

54
spring-test/src/main/java/org/springframework/test/context/DefaultTestContext.java → spring-test/src/main/java/org/springframework/test/context/support/DefaultTestContext.java

@ -1,5 +1,5 @@ @@ -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 @@ @@ -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; @@ -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.
*
* <p>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 @@ -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.
* <p>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 <em>dirty</em> (i.e., by removing it from the
* context cache and closing it).
* <p>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);
}

8
spring-test/src/test/java/org/springframework/test/context/TestContextTestUtils.java

@ -1,5 +1,5 @@ @@ -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 { @@ -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();
}
}

Loading…
Cancel
Save