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
This commit is contained in:
parent
0392a88c69
commit
186abcb054
|
@ -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();
|
||||
|
|
|
@ -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;
|
|||
*
|
||||
* <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.
|
||||
*
|
||||
|
@ -58,6 +57,46 @@ public interface TestContextBootstrapper {
|
|||
*/
|
||||
BootstrapContext getBootstrapContext();
|
||||
|
||||
/**
|
||||
* 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()
|
||||
*/
|
||||
TestContext buildTestContext();
|
||||
|
||||
/**
|
||||
* Build the {@linkplain MergedContextConfiguration merged context configuration}
|
||||
* for the test class in the {@link BootstrapContext} associated with this
|
||||
* bootstrapper.
|
||||
* <p>Implementations must take the following into account when building the
|
||||
* merged configuration:
|
||||
* <ul>
|
||||
* <li>Context hierarchies declared via {@link ContextHierarchy @ContextHierarchy}
|
||||
* and {@link ContextConfiguration @ContextConfiguration}</li>
|
||||
* <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>
|
||||
* <li>If a {@code ContextLoader} class has been explicitly declared via
|
||||
* {@link ContextConfiguration#loader}, use it.</li>
|
||||
* <li>Otherwise, concrete implementations are free to determine which
|
||||
* {@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.
|
||||
|
@ -82,31 +121,4 @@ public interface TestContextBootstrapper {
|
|||
*/
|
||||
List<TestExecutionListener> getTestExecutionListeners();
|
||||
|
||||
/**
|
||||
* Build the {@linkplain MergedContextConfiguration merged context configuration}
|
||||
* for the test class in the {@link BootstrapContext} associated with this
|
||||
* bootstrapper.
|
||||
* <p>Implementations must take the following into account when building the
|
||||
* merged configuration:
|
||||
* <ul>
|
||||
* <li>Context hierarchies declared via {@link ContextHierarchy @ContextHierarchy}
|
||||
* and {@link ContextConfiguration @ContextConfiguration}</li>
|
||||
* <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>
|
||||
* </ul>
|
||||
* <p>Consult the Javadoc for the aforementioned annotations for details on
|
||||
* the required semantics.
|
||||
* <p>When determining which {@link ContextLoader} to use for a given test
|
||||
* class, the following algorithm should be used:
|
||||
* <ol>
|
||||
* <li>If a {@code ContextLoader} class has been explicitly declared via
|
||||
* {@link ContextConfiguration#loader}, use it.</li>
|
||||
* <li>Otherwise, concrete implementations are free to determine which
|
||||
* {@code ContextLoader} class to use as as default.</li>
|
||||
* </ol>
|
||||
* @return the merged context configuration, never {@code null}
|
||||
*/
|
||||
MergedContextConfiguration buildMergedContextConfiguration();
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
|||
* 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 {
|
|||
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 + "]");
|
||||
|
|
|
@ -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()}.
|
||||
* <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}
|
||||
*/
|
||||
|
|
|
@ -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.
|
||||
*
|
||||
* <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
|
|||
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue