Spring TestContext Framework for comprehensive integration testing of Spring applications
The TestContext Framework is the foundation of Spring's testing support, providing ApplicationContext management, dependency injection, and transaction support for integration tests. It's designed to be testing framework-agnostic, supporting JUnit 4, JUnit 5, and TestNG.
Encapsulates the context of a test execution, providing access to the ApplicationContext and test metadata.
/**
* TestContext encapsulates the context in which a test is executed,
* agnostic of the actual testing framework in use.
*/
public interface TestContext extends AttributeAccessor, Serializable {
/**
* Get the application context for this test context
* @return the application context (never null)
* @throws IllegalStateException if an error occurs while retrieving the application context
*/
ApplicationContext getApplicationContext();
/**
* Determine if an application context has been loaded for this test context
* @return true if the application context has been loaded
*/
boolean hasApplicationContext();
/**
* Get the test class for this test context
* @return the test class (never null)
*/
Class<?> getTestClass();
/**
* Get the current test instance for this test context
* Note: this is a mutable property.
* @return the current test instance (never null)
*/
Object getTestInstance();
/**
* Get the current test method for this test context
* Note: this is a mutable property.
* @return the current test method (never null)
*/
Method getTestMethod();
/**
* Get the exception that was thrown during execution of the test method
* @return the exception that was thrown, or null if no exception was thrown
*/
@Nullable
Throwable getTestException();
/**
* Call this method to signal that the application context associated with this test context is dirty
* and should be removed from the context cache
*/
void markApplicationContextDirty(@Nullable DirtiesContext.HierarchyMode hierarchyMode);
/**
* Update this test context to reflect the state of the currently executing test
* @param testInstance the current test instance (may be null)
* @param testMethod the current test method (may be null)
* @param testException the exception that was thrown in the test method, or null if no exception was thrown
*/
void updateState(@Nullable Object testInstance, @Nullable Method testMethod, @Nullable Throwable testException);
/**
* Publish the ApplicationEvent created by the given eventFactory
* to the application context for this test context.
* The ApplicationEvent will only be published if the application context is available.
* @param eventFactory factory for lazy creation of the ApplicationEvent
* @since 5.2
*/
default void publishEvent(Function<TestContext, ? extends ApplicationEvent> eventFactory);
/**
* Set the MethodInvoker to use.
* By default, this method does nothing.
* @param methodInvoker the MethodInvoker to use
* @since 6.1
*/
default void setMethodInvoker(MethodInvoker methodInvoker);
/**
* Get the MethodInvoker to use.
* By default, this method returns MethodInvoker.DEFAULT_INVOKER.
* @return the MethodInvoker to use
* @since 6.1
*/
default MethodInvoker getMethodInvoker();
}The main entry point for the TestContext Framework, responsible for managing TestContext and TestExecutionListener instances.
/**
* TestContextManager is the main entry point into the Spring TestContext Framework.
* Manages a single TestContext and signals events to each registered TestExecutionListener.
*/
public class TestContextManager {
/**
* Construct a new TestContextManager for the specified test class
* @param testClass the test class to be managed
*/
public TestContextManager(Class<?> testClass);
/**
* Get the TestContext managed by this TestContextManager
* @return the TestContext (never null)
*/
public final TestContext getTestContext();
/**
* Hook for pre-processing a test class before execution of any tests within the class.
* Should be called prior to any framework-specific before class methods.
* @throws Exception if an error occurs
*/
public void beforeTestClass() throws Exception;
/**
* Hook for preparing a test instance prior to execution of any individual test methods.
* Should be called immediately after instantiation of the test instance.
* @param testInstance the test instance to prepare
* @throws Exception if an error occurs while preparing the test instance
*/
public void prepareTestInstance(Object testInstance) throws Exception;
/**
* Hook for pre-processing a test method before execution of the actual test method.
* Should be called prior to any framework-specific before methods.
* @param testInstance the current test instance
* @param testMethod the test method which is about to be executed
* @throws Exception if an error occurs
*/
public void beforeTestMethod(Object testInstance, Method testMethod) throws Exception;
/**
* Hook for pre-processing a test immediately before execution of the test method.
* Should be called after any framework-specific before methods.
* @param testInstance the current test instance
* @param testMethod the test method which is about to be executed
* @throws Exception if an error occurs
*/
public void beforeTestExecution(Object testInstance, Method testMethod) throws Exception;
/**
* Hook for post-processing a test immediately after execution of the test method.
* Should be called before any framework-specific after methods.
* @param testInstance the current test instance
* @param testMethod the test method which has just been executed
* @param exception the exception that was thrown during execution, or null if none
* @throws Exception if an error occurs
*/
public void afterTestExecution(Object testInstance, Method testMethod, @Nullable Throwable exception) throws Exception;
/**
* Hook for post-processing a test method after execution of the actual test method.
* Should be called after any framework-specific after methods.
* @param testInstance the current test instance
* @param testMethod the test method which has just been executed
* @param exception the exception that was thrown during test method execution or by a TestExecutionListener, or null if none
* @throws Exception if an error occurs
*/
public void afterTestMethod(Object testInstance, Method testMethod, @Nullable Throwable exception) throws Exception;
/**
* Hook for post-processing a test class after execution of all tests within the class.
* Should be called after any framework-specific after class methods.
* @throws Exception if an error occurs
*/
public void afterTestClass() throws Exception;
}Defines a listener API for reacting to test execution events published by the TestContextManager.
/**
* TestExecutionListener defines a listener API for reacting to test execution events
* published by the TestContextManager with which the listener is registered.
*/
public interface TestExecutionListener extends Ordered {
/**
* Pre-processes a test class before execution of all tests within the class.
* @param testContext the test context for the test; never null
* @throws Exception allows any exception to propagate
*/
default void beforeTestClass(TestContext testContext) throws Exception {}
/**
* Prepares the test instance of the supplied test context.
* @param testContext the test context for the test; never null
* @throws Exception allows any exception to propagate
*/
default void prepareTestInstance(TestContext testContext) throws Exception {}
/**
* Pre-processes a test method before execution of the actual test method.
* @param testContext the test context in which the test method will be executed; never null
* @throws Exception allows any exception to propagate
*/
default void beforeTestMethod(TestContext testContext) throws Exception {}
/**
* Pre-processes a test immediately before execution of the test method in the supplied test context.
* @param testContext the test context in which the test method will be executed; never null
* @throws Exception allows any exception to propagate
*/
default void beforeTestExecution(TestContext testContext) throws Exception {}
/**
* Post-processes a test immediately after execution of the test method in the supplied test context.
* @param testContext the test context in which the test method was executed; never null
* @throws Exception allows any exception to propagate
*/
default void afterTestExecution(TestContext testContext) throws Exception {}
/**
* Post-processes a test method after execution of the actual test method.
* @param testContext the test context in which the test method was executed; never null
* @throws Exception allows any exception to propagate
*/
default void afterTestMethod(TestContext testContext) throws Exception {}
/**
* Post-processes a test class after execution of all tests within the class.
* @param testContext the test context for the test; never null
* @throws Exception allows any exception to propagate
*/
default void afterTestClass(TestContext testContext) throws Exception {}
}Spring provides several built-in TestExecutionListener implementations for common testing scenarios.
/**
* TestExecutionListener that provides support for dependency injection and initialization
* of test instances.
*/
public class DependencyInjectionTestExecutionListener extends AbstractTestExecutionListener {
@Override
public void prepareTestInstance(TestContext testContext) throws Exception;
}
/**
* TestExecutionListener that provides support for executing tests within transactions.
*/
public class TransactionalTestExecutionListener extends AbstractTestExecutionListener {
@Override
public void beforeTestMethod(TestContext testContext) throws Exception;
@Override
public void afterTestMethod(TestContext testContext) throws Exception;
}
/**
* TestExecutionListener that processes @DirtiesContext annotations.
*/
public class DirtiesContextTestExecutionListener extends AbstractTestExecutionListener {
@Override
public void beforeTestMethod(TestContext testContext) throws Exception;
@Override
public void afterTestMethod(TestContext testContext) throws Exception;
@Override
public void afterTestClass(TestContext testContext) throws Exception;
}
/**
* TestExecutionListener that provides support for executing SQL scripts configured via @Sql.
*/
public class SqlScriptsTestExecutionListener extends AbstractTestExecutionListener {
@Override
public void beforeTestMethod(TestContext testContext) throws Exception;
@Override
public void afterTestMethod(TestContext testContext) throws Exception;
}
/**
* TestExecutionListener that provides support for ApplicationEvents published during test execution.
*/
public class ApplicationEventsTestExecutionListener extends AbstractTestExecutionListener {
@Override
public void prepareTestInstance(TestContext testContext) throws Exception;
@Override
public void beforeTestMethod(TestContext testContext) throws Exception;
@Override
public void afterTestMethod(TestContext testContext) throws Exception;
}Core annotations for configuring the ApplicationContext in tests.
/**
* @ContextConfiguration defines class-level metadata that is used to determine
* how to load and configure an ApplicationContext for integration tests.
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface ContextConfiguration {
/**
* Alias for locations()
* @return an array of resource locations
*/
@AliasFor("locations")
String[] value() default {};
/**
* The resource locations to use for loading an ApplicationContext.
* @return an array of resource locations
*/
@AliasFor("value")
String[] locations() default {};
/**
* The component classes to use for loading an ApplicationContext.
* @return an array of component classes
*/
Class<?>[] classes() default {};
/**
* The application context initializer classes to use for initializing a ConfigurableApplicationContext.
* @return an array of ApplicationContextInitializer classes
*/
Class<? extends ApplicationContextInitializer<?>>[] initializers() default {};
/**
* Whether or not resource locations or component classes from test superclasses should be inherited.
* @return true if locations should be inherited
*/
boolean inheritLocations() default true;
/**
* Whether or not context initializers from test superclasses should be inherited.
* @return true if initializers should be inherited
*/
boolean inheritInitializers() default true;
/**
* The type of ContextLoader to use for loading an ApplicationContext.
* @return the ContextLoader class
*/
Class<? extends ContextLoader> loader() default ContextLoader.class;
/**
* The name of the context hierarchy level represented by this configuration.
* @return the name of the context hierarchy level
*/
String name() default "";
}
/**
* @ContextHierarchy is a class-level annotation that is used to define a hierarchy
* of ApplicationContexts for integration tests.
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface ContextHierarchy {
/**
* A list of @ContextConfiguration instances, each of which defines a level
* in the context hierarchy.
* @return an array of @ContextConfiguration instances
*/
ContextConfiguration[] value();
}
/**
* @ActiveProfiles is a class-level annotation that is used to declare which active bean definition
* profiles should be used when loading an ApplicationContext for an integration test.
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
public @interface ActiveProfiles {
/**
* Alias for profiles()
* @return the set of active profiles
*/
@AliasFor("profiles")
String[] value() default {};
/**
* The bean definition profiles to activate.
* @return the set of active profiles
*/
@AliasFor("value")
String[] profiles() default {};
/**
* The type of ActiveProfilesResolver to use for resolving the active profiles.
* @return the ActiveProfilesResolver class
*/
Class<? extends ActiveProfilesResolver> resolver() default ActiveProfilesResolver.class;
/**
* Whether or not active profiles from test superclasses should be inherited.
* @return true if active profiles should be inherited
*/
boolean inheritProfiles() default true;
}Usage Examples:
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.ActiveProfiles;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
// Basic configuration with Java config
@SpringJUnitConfig(AppConfig.class)
class BasicIntegrationTest {
@Autowired
private UserService userService;
@Test
void testUserService() {
// test implementation
}
}
// Configuration with XML
@ContextConfiguration(locations = "/test-config.xml")
@ExtendWith(SpringExtension.class)
class XmlConfigTest {
// test implementation
}
// Multiple configuration files
@ContextConfiguration(classes = {DatabaseConfig.class, ServiceConfig.class})
@ActiveProfiles({"test", "embedded"})
@ExtendWith(SpringExtension.class)
class MultiConfigTest {
// test implementation
}
// Context hierarchy for complex scenarios
@ContextHierarchy({
@ContextConfiguration(name = "parent", classes = ParentConfig.class),
@ContextConfiguration(name = "child", classes = ChildConfig.class)
})
@ExtendWith(SpringExtension.class)
class HierarchyTest {
// test implementation
}Strategy interfaces for loading ApplicationContext instances.
/**
* Strategy interface for loading an ApplicationContext for an integration test
* managed by the Spring TestContext Framework.
*/
public interface ContextLoader {
/**
* Process the given array of (potentially generic) resource locations and return
* an array of processed locations.
* @param clazz the class with which the locations are associated
* @param locations the unprocessed resource locations to process
* @return an array of processed resource locations
*/
String[] processLocations(Class<?> clazz, String... locations);
/**
* Load a new ApplicationContext based on the supplied resource locations.
* @param locations the resource locations to load
* @return a new application context
* @throws Exception if context loading failed
*/
ApplicationContext loadContext(String... locations) throws Exception;
}
/**
* Enhanced ContextLoader SPI that supplies a MergedContextConfiguration to
* load an ApplicationContext.
*/
public interface SmartContextLoader extends ContextLoader {
/**
* Load a new ApplicationContext based on the supplied MergedContextConfiguration.
* @param mergedConfig the merged context configuration to use to load the context
* @return a new application context
* @throws Exception if context loading failed
*/
ApplicationContext loadContext(MergedContextConfiguration mergedConfig) throws Exception;
/**
* Process the ContextConfigurationAttributes for a given test class.
* @param configAttributes the context configuration attributes to process
*/
void processContextConfiguration(ContextConfigurationAttributes configAttributes);
}
/**
* Generic utility class for working with context loaders.
*/
public abstract class ContextLoaderUtils {
/**
* Resolve the ContextLoader class to use for the supplied test class.
* @param testClass the test class for which the ContextLoader should be resolved
* @return the ContextLoader class to use
*/
public static Class<? extends ContextLoader> resolveContextLoaderClass(Class<?> testClass);
}/**
* Holder for merged context configuration containing the merged values from
* all ContextConfiguration annotations in a test class hierarchy.
*/
public class MergedContextConfiguration implements Serializable {
public MergedContextConfiguration(Class<?> testClass,
String[] locations,
Class<?>[] classes,
Set<Class<? extends ApplicationContextInitializer<?>>> contextInitializerClasses,
ActiveProfilesResolver activeProfilesResolver,
ContextLoader contextLoader);
public Class<?> getTestClass();
public String[] getLocations();
public Class<?>[] getClasses();
public Set<Class<? extends ApplicationContextInitializer<?>>> getContextInitializerClasses();
public String[] getActiveProfiles();
public ContextLoader getContextLoader();
}
/**
* Encapsulates the context configuration attributes declared on a test class
* via @ContextConfiguration.
*/
public class ContextConfigurationAttributes {
public ContextConfigurationAttributes(Class<?> declaringClass, ContextConfiguration contextConfiguration);
public Class<?> getDeclaringClass();
public String[] getLocations();
public Class<?>[] getClasses();
public boolean isInheritLocations();
public Class<? extends ContextLoader> getContextLoaderClass();
}
/**
* Strategy interface for resolving active bean definition profiles programmatically.
*/
public interface ActiveProfilesResolver {
/**
* Resolve the bean definition profiles to activate for the given test class.
* @param testClass the test class for which profiles should be resolved
* @return the set of active profiles for the test class, or an empty array if no profiles are active
*/
String[] resolve(Class<?> testClass);
}Install with Tessl CLI
npx tessl i tessl/maven-org-springframework--spring-test