Lightweight application context testing utilities for testing auto-configurations and components in isolation without full application startup.
org.springframework.boot.test.context.runner
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.boot.test.context.runner.WebApplicationContextRunner;
import org.springframework.boot.test.context.runner.ReactiveWebApplicationContextRunner;
import org.springframework.boot.test.context.runner.ContextConsumer;
import org.springframework.boot.test.context.assertj.AssertableApplicationContext;
import org.springframework.beans.factory.config.BeanDefinitionCustomizer;
import static org.assertj.core.api.Assertions.assertThat;Full Package: org.springframework.boot.test.context.runner.ContextConsumer
Functional interface for processing an ApplicationContext with the ability to throw checked exceptions. Used as the callback parameter in run() and prepare() methods of context runners.
/**
* Callback interface used to process an ApplicationContext with the ability to throw a checked exception
* @param <C> the application context type
* @since 2.0.0
*/
@FunctionalInterface
public interface ContextConsumer<C extends ApplicationContext> {
/**
* Performs this operation on the supplied context
* @param context the application context to consume
* @throws Throwable any exception that might occur in assertions
*/
void accept(C context) throws Throwable;
/**
* Returns a composed ContextConsumer that performs, in sequence, this operation followed by the after operation
* @param after the operation to perform after this operation
* @return a composed ContextConsumer that performs in sequence this operation followed by the after operation
* @since 2.6.0
*/
default ContextConsumer<C> andThen(ContextConsumer<? super C> after);
}Usage Examples:
// Simple usage
contextRunner.run(context -> {
assertThat(context).hasSingleBean(MyService.class);
});
// Chained usage with andThen
ContextConsumer<AssertableApplicationContext> checkBeans = context ->
assertThat(context).hasSingleBean(DataSource.class);
ContextConsumer<AssertableApplicationContext> checkProperties = context ->
assertThat(context.getEnvironment().getProperty("app.name")).isEqualTo("test");
contextRunner.run(checkBeans.andThen(checkProperties));Full Package: org.springframework.boot.test.context.runner.ApplicationContextRunner
Non-web context runner for standard application context testing.
public final class ApplicationContextRunner
extends AbstractApplicationContextRunner<
ApplicationContextRunner,
ConfigurableApplicationContext,
AssertableApplicationContext> {
public ApplicationContextRunner(); // Default constructor
public ApplicationContextRunner(Supplier<ConfigurableApplicationContext> contextFactory);
public ApplicationContextRunner(Supplier<ConfigurableApplicationContext> contextFactory, Class<?>... additionalContextInterfaces); // @since 3.4.0
}// Configuration
withUserConfiguration(Class<?>... configurationClasses)
withConfiguration(Configurations configurations)
withPropertyValues(String... pairs) // "key=value"
withSystemProperties(String... pairs) // Temporary
withBean(Class<T> type, Object... constructorArgs)
withBean(String name, Class<T> type, Supplier<T> supplier)
withInitializer(ApplicationContextInitializer<...> initializer)
withParent(ApplicationContext parent)
withAllowBeanDefinitionOverriding(boolean allow)
// Execution
run(ContextConsumer<AssertableApplicationContext> consumer) // Runs and auto-closes
prepare(ContextConsumer<AssertableApplicationContext> consumer) // Prepares without refreshimport org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.boot.autoconfigure.AutoConfiguration;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.context.annotation.Bean;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
@AutoConfiguration
@ConditionalOnProperty("feature.enabled")
class MyAutoConfiguration {
@Bean
public MyService myService() {
return new MyService();
}
}
class MyAutoConfigurationTest {
private final ApplicationContextRunner contextRunner =
new ApplicationContextRunner()
.withUserConfiguration(MyAutoConfiguration.class);
@Test
void whenPropertySet_beanCreated() {
contextRunner
.withPropertyValues("feature.enabled=true")
.run(context -> {
assertThat(context).hasSingleBean(MyService.class);
assertThat(context).hasBean("myService");
});
}
@Test
void whenPropertyNotSet_beanNotCreated() {
contextRunner
.run(context -> {
assertThat(context).doesNotHaveBean(MyService.class);
});
}
}@Test
void whenInvalidConfig_contextFails() {
contextRunner
.withUserConfiguration(InvalidConfig.class)
.run(context -> {
assertThat(context).hasFailed();
assertThat(context).getFailure()
.isInstanceOf(BeanCreationException.class)
.hasMessageContaining("expected error");
});
}@Test
void testWithRegisteredBean() {
contextRunner
.withBean("customService", MyService.class, () -> new MyService("test"))
.run(context -> {
assertThat(context).hasBean("customService");
MyService service = context.getBean("customService", MyService.class);
assertThat(service.getName()).isEqualTo("test");
});
}import org.springframework.boot.test.context.FilteredClassLoader;
@Test
void whenClassMissing_fallbackUsed() {
contextRunner
.withClassLoader(new FilteredClassLoader(SomeClass.class))
.withUserConfiguration(MyAutoConfiguration.class)
.run(context -> {
assertThat(context).hasBean("fallbackBean");
});
}Full Package: org.springframework.boot.test.context.runner.WebApplicationContextRunner
Servlet-based web context runner for testing web components with MockServletContext.
public final class WebApplicationContextRunner
extends AbstractApplicationContextRunner<
WebApplicationContextRunner,
ConfigurableWebApplicationContext,
AssertableWebApplicationContext> {
/**
* Create a new WebApplicationContextRunner with MockServletContext
* Uses AnnotationConfigServletWebApplicationContext with MockServletContext
* @since 2.0.0
*/
public WebApplicationContextRunner();
/**
* Create with a custom context factory
* @param contextFactory supplier that returns new context instance
* @since 2.0.0
*/
public WebApplicationContextRunner(Supplier<ConfigurableWebApplicationContext> contextFactory);
/**
* Create with custom factory and additional interfaces
* @param contextFactory supplier that returns new context instance
* @param additionalContextInterfaces additional interfaces for context proxy
* @since 3.4.0
*/
public WebApplicationContextRunner(Supplier<ConfigurableWebApplicationContext> contextFactory, Class<?>... additionalContextInterfaces);
/**
* Decorate a context factory to set MockServletContext on each new context
* Useful for custom WebApplicationContext implementations
* @param contextFactory the context factory to decorate
* @return decorated supplier that sets MockServletContext
* @since 2.0.0
*/
public static Supplier<ConfigurableWebApplicationContext> withMockServletContext(
Supplier<ConfigurableWebApplicationContext> contextFactory);
}Usage Examples:
// Default usage - automatically includes MockServletContext
new WebApplicationContextRunner()
.withUserConfiguration(WebMvcConfig.class)
.run(context -> {
assertThat(context).hasSingleBean(DispatcherServlet.class);
assertThat(context.getServletContext()).isInstanceOf(MockServletContext.class);
});
// Custom context factory with MockServletContext
new WebApplicationContextRunner(
WebApplicationContextRunner.withMockServletContext(
() -> new CustomWebApplicationContext()
)
)
.run(context -> {
assertThat(context).isInstanceOf(CustomWebApplicationContext.class);
assertThat(context.getServletContext()).isNotNull();
});Full Package: org.springframework.boot.test.context.runner.ReactiveWebApplicationContextRunner
Reactive web context runner.
public final class ReactiveWebApplicationContextRunner
extends AbstractApplicationContextRunner<
ReactiveWebApplicationContextRunner,
ConfigurableReactiveWebApplicationContext,
AssertableReactiveWebApplicationContext> {
public ReactiveWebApplicationContextRunner(); // Available since 2.0.0 (when class was introduced)
public ReactiveWebApplicationContextRunner(Supplier<ConfigurableReactiveWebApplicationContext> contextFactory); // @since 3.4.0
public ReactiveWebApplicationContextRunner(Supplier<ConfigurableReactiveWebApplicationContext> contextFactory, Class<?>... additionalContextInterfaces); // @since 3.4.0
}Full Package: org.springframework.boot.test.context.FilteredClassLoader
Test classloader that filters specific classes/packages.
public class FilteredClassLoader extends URLClassLoader implements SmartClassLoader {
public FilteredClassLoader(Class<?>... hiddenClasses);
public FilteredClassLoader(ClassLoader parent, Class<?>... hiddenClasses);
public FilteredClassLoader(String... hiddenPackages);
public FilteredClassLoader(ClassPathResource... hiddenResources);
public FilteredClassLoader(Predicate<String>... filters);
// SmartClassLoader support
public Class<?> publicDefineClass(String name, byte[] b, ProtectionDomain protectionDomain);
// Nested Filter Classes
public static final class ClassFilter implements Predicate<String> {
public static ClassFilter of(Class<?>... hiddenClasses);
}
public static final class PackageFilter implements Predicate<String> {
public static PackageFilter of(String... hiddenPackages);
}
public static final class ClassPathResourceFilter implements Predicate<String> {
public static ClassPathResourceFilter of(ClassPathResource... hiddenResources);
}
}Full Package: org.springframework.boot.test.context.runner.AbstractApplicationContextRunner<SELF, C, A>
// Configuration Methods
public SELF withUserConfiguration(Class<?>... configurationClasses);
public SELF withConfiguration(Configurations configurations);
// Property Management
public SELF withPropertyValues(String... pairs); // "key=value" format
public SELF withSystemProperties(String... pairs); // Temporary, removed after test
// Bean Registration
public <T> SELF withBean(Class<T> type, Object... constructorArgs);
public <T> SELF withBean(@Nullable String name, Class<T> type, Object... constructorArgs);
public <T> SELF withBean(Class<T> type, Supplier<T> supplier, BeanDefinitionCustomizer... customizers);
public <T> SELF withBean(@Nullable String name, Class<T> type, Supplier<T> supplier, BeanDefinitionCustomizer... customizers);
// Customization
public SELF with(Function<SELF, SELF> customizer);
public SELF withInitializer(ApplicationContextInitializer<? super C> initializer);
// Context Configuration
public SELF withClassLoader(@Nullable ClassLoader classLoader);
public SELF withParent(ApplicationContext parent);
public SELF withAllowBeanDefinitionOverriding(boolean allowBeanDefinitionOverriding);
public SELF withAllowCircularReferences(boolean allowCircularReferences);
// Execution
public SELF run(ContextConsumer<? super A> consumer);
public SELF prepare(ContextConsumer<? super A> consumer); // Since 3.0.0Full Package: org.springframework.boot.test.context.FilteredClassLoader
Since: 2.0.0
public class FilteredClassLoader extends URLClassLoader implements SmartClassLoader {
// Constructors
public FilteredClassLoader(Class<?>... hiddenClasses);
public FilteredClassLoader(ClassLoader parent, Class<?>... hiddenClasses);
public FilteredClassLoader(String... hiddenPackages);
public FilteredClassLoader(ClassPathResource... hiddenResources);
public FilteredClassLoader(Predicate<String>... filters);
// SmartClassLoader support
public Class<?> publicDefineClass(String name, byte[] b, @Nullable ProtectionDomain protectionDomain);
// Nested Filter Classes
public static final class ClassFilter implements Predicate<String> {
public static ClassFilter of(Class<?>... hiddenClasses);
}
public static final class PackageFilter implements Predicate<String> {
public static PackageFilter of(String... hiddenPackages);
}
public static final class ClassPathResourceFilter implements Predicate<String> {
public static ClassPathResourceFilter of(ClassPathResource... hiddenResources);
}
}Full Package: org.springframework.boot.test.context.runner.WebApplicationContextRunner
public final class WebApplicationContextRunner
extends AbstractApplicationContextRunner<...> {
public WebApplicationContextRunner();
public WebApplicationContextRunner(Supplier<ConfigurableWebApplicationContext> contextFactory);
// Utility for creating context with MockServletContext
@Contract("!null -> !null")
public static @Nullable Supplier<ConfigurableWebApplicationContext> withMockServletContext(
@Nullable Supplier<ConfigurableWebApplicationContext> contextFactory
);
}import org.springframework.context.annotation.AnnotationConfigApplicationContext;
@Test
void testWithCustomContextFactory() {
new ApplicationContextRunner(() -> {
AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext();
context.setDisplayName("CustomTestContext");
return context;
})
.withUserConfiguration(MyConfig.class)
.run(context -> {
assertThat(context.getDisplayName()).contains("CustomTestContext");
});
}@Test
void testWithParentContext() {
ApplicationContext parent = new AnnotationConfigApplicationContext(ParentConfig.class);
new ApplicationContextRunner()
.withParent(parent)
.withUserConfiguration(ChildConfig.class)
.run(context -> {
// Child can access parent beans
assertThat(context.getBean(ParentBean.class)).isNotNull();
assertThat(context.getBean(ChildBean.class)).isNotNull();
});
}@Test
void testPrepareWithoutRefresh() {
new ApplicationContextRunner()
.withUserConfiguration(MyConfig.class)
.prepare(context -> {
// Context is prepared but not refreshed
// Useful for testing initialization logic
assertThat(context.getBeanFactory()).isNotNull();
assertThat(context.isActive()).isFalse();
});
}@Test
void testWithMultipleFilteredClasses() {
ClassLoader filteredLoader = new FilteredClassLoader(
HikariDataSource.class,
PostgreSQLDriver.class
);
contextRunner
.withClassLoader(filteredLoader)
.withUserConfiguration(DataSourceAutoConfiguration.class)
.run(context -> {
// Should use H2 fallback when PostgreSQL not available
assertThat(context).hasSingleBean(DataSource.class);
assertThat(context.getBean(DataSource.class))
.isNotInstanceOf(HikariDataSource.class);
});
}@Test
void testWithFilteredPackages() {
ClassLoader filteredLoader = new FilteredClassLoader(
"com.zaxxer.hikari",
"org.postgresql"
);
contextRunner
.withClassLoader(filteredLoader)
.withUserConfiguration(MyAutoConfiguration.class)
.run(context -> {
assertThat(context).doesNotHaveBean("hikariDataSource");
});
}import org.springframework.core.io.ClassPathResource;
@Test
void testWithFilteredResources() {
ClassLoader filteredLoader = new FilteredClassLoader(
new ClassPathResource("application.properties"),
new ClassPathResource("config/application.yml")
);
contextRunner
.withClassLoader(filteredLoader)
.withUserConfiguration(MyConfig.class)
.run(context -> {
// Configuration should use defaults when files not found
assertThat(context.getEnvironment().getProperty("custom.property"))
.isNull();
});
}@Configuration
class OriginalConfig {
@Bean
public MyService myService() {
return new OriginalServiceImpl();
}
}
@Configuration
class OverrideConfig {
@Bean
public MyService myService() {
return new OverriddenServiceImpl();
}
}
@Test
void testBeanOverriding() {
new ApplicationContextRunner()
.withAllowBeanDefinitionOverriding(true)
.withUserConfiguration(OriginalConfig.class, OverrideConfig.class)
.run(context -> {
assertThat(context.getBean(MyService.class))
.isInstanceOf(OverriddenServiceImpl.class);
});
}@Test
void testWithSystemProperties() {
new ApplicationContextRunner()
.withSystemProperties(
"java.io.tmpdir=/custom/tmp",
"user.timezone=UTC"
)
.withUserConfiguration(SystemPropertiesConfig.class)
.run(context -> {
// System properties are set during test and restored after
assertThat(System.getProperty("java.io.tmpdir"))
.isEqualTo("/custom/tmp");
MyService service = context.getBean(MyService.class);
assertThat(service.getTmpDir()).isEqualTo("/custom/tmp");
});
// System properties restored here
}@Test
void testCircularReferences() {
new ApplicationContextRunner()
.withAllowCircularReferences(true)
.withUserConfiguration(CircularConfig.class)
.run(context -> {
// Context loads successfully despite circular references
assertThat(context).hasSingleBean(ServiceA.class);
assertThat(context).hasSingleBean(ServiceB.class);
});
}@Test
void testWithBeanCustomizers() {
new ApplicationContextRunner()
.withBean("myService", MyService.class,
() -> new MyService("test"),
bd -> {
bd.setScope(BeanDefinition.SCOPE_PROTOTYPE);
bd.setLazyInit(true);
})
.run(context -> {
BeanDefinition bd = context.getBeanFactory()
.getBeanDefinition("myService");
assertThat(bd.getScope()).isEqualTo(BeanDefinition.SCOPE_PROTOTYPE);
assertThat(bd.isLazyInit()).isTrue();
});
}@Test
void testWithInitializers() {
new ApplicationContextRunner()
.withInitializer(context -> {
context.getBeanFactory().registerSingleton("earlyBean", new EarlyBean());
})
.withUserConfiguration(MyConfig.class)
.run(context -> {
assertThat(context).hasBean("earlyBean");
});
}private ApplicationContextRunner baseRunner() {
return new ApplicationContextRunner()
.withPropertyValues("app.name=test")
.withUserConfiguration(BaseConfig.class);
}
@Test
void testWithCustomizer() {
baseRunner()
.with(runner -> runner
.withPropertyValues("app.feature=enabled")
.withBean(FeatureService.class))
.run(context -> {
assertThat(context).hasBean("featureService");
});
}@Test
void testReactiveWebContext() {
new ReactiveWebApplicationContextRunner()
.withUserConfiguration(ReactiveWebConfig.class)
.run(context -> {
assertThat(context).hasSingleBean(WebFilter.class);
assertThat(context).hasSingleBean(RouterFunction.class);
});
}@Test
void testWebContextWithServlet() {
new WebApplicationContextRunner()
.withUserConfiguration(WebConfig.class)
.run(context -> {
assertThat(context).hasSingleBean(ServletRegistrationBean.class);
assertThat(context.getServletContext()).isNotNull();
});
}abstract class AutoConfigurationTestBase {
protected final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(
MyAutoConfiguration.class,
DependencyAutoConfiguration.class
))
.withPropertyValues(
"logging.level.test=DEBUG",
"spring.main.banner-mode=off"
);
@Test
void testCommonBehavior() {
contextRunner.run(context -> {
assertThat(context).hasBean("commonBean");
});
}
}
class SpecificAutoConfigTest extends AutoConfigurationTestBase {
@Test
void testSpecificFeature() {
contextRunner
.withPropertyValues("feature.enabled=true")
.run(context -> {
assertThat(context).hasBean("featureBean");
});
}
}@AutoConfiguration
@ConditionalOnClass(DataSource.class)
@ConditionalOnProperty(name = "datasource.enabled", havingValue = "true")
class DataSourceAutoConfiguration {
@Bean
public DataSource dataSource() {
return new EmbeddedDataSource();
}
}
class DataSourceAutoConfigurationTest {
private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
.withConfiguration(AutoConfigurations.of(DataSourceAutoConfiguration.class));
@Test
void whenClassPresent_andPropertySet_beanCreated() {
contextRunner
.withPropertyValues("datasource.enabled=true")
.run(context -> {
assertThat(context).hasSingleBean(DataSource.class);
});
}
@Test
void whenPropertyNotSet_beanNotCreated() {
contextRunner
.run(context -> {
assertThat(context).doesNotHaveBean(DataSource.class);
});
}
@Test
void whenClassAbsent_beanNotCreated() {
contextRunner
.withClassLoader(new FilteredClassLoader(DataSource.class))
.withPropertyValues("datasource.enabled=true")
.run(context -> {
assertThat(context).doesNotHaveBean(DataSource.class);
});
}
}@Test
void testFailureScenarios() {
contextRunner
.withUserConfiguration(InvalidConfig.class)
.run(context -> {
// Assert context failed to start
assertThat(context).hasFailed();
// Assert on failure type
assertThat(context).getFailure()
.isInstanceOf(BeanCreationException.class)
.hasMessageContaining("Could not create bean");
// Assert on root cause
assertThat(context).getFailure()
.getRootCause()
.isInstanceOf(IllegalStateException.class)
.hasMessage("Invalid configuration");
});
}Issue: Beans not found in context
contextRunner
.withUserConfiguration(MyConfig.class, DependencyConfig.class)
.run(context -> { /* test */ });Issue: Properties not applied
withPropertyValues("server.port=8080") not "server.port: 8080"Issue: Context doesn't fail as expected
.run(context -> {
assertThat(context).hasFailed();
context.getFailure().printStackTrace(); // Debug output
});Issue: Filtered class not working
Issue: System properties persist after test
Issue: Bean definition overriding not allowed
Issue: Circular dependency error
Issue: Wrong context type loaded
Issue: MockServletContext not available in web runner
Issue: Parent context beans not accessible
Error: "BeanDefinitionOverrideException"
Error: "UnsatisfiedDependencyException"
Error: "NoSuchBeanDefinitionException"
Error: "BeanCurrentlyInCreationException"