CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-org-springframework-boot--spring-boot-test

Spring Boot Test provides comprehensive testing support and utilities for Spring Boot applications

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

index.mddocs/

Spring Boot Test

Spring Boot Test is a comprehensive testing library that provides specialized annotations, utilities, and auto-configuration capabilities for testing Spring Boot applications. It offers full integration testing with @SpringBootTest, isolated slice testing with context runners, extensive JSON testing support, output capture utilities, and rich AssertJ-based assertions for validating application contexts and beans.

Package Information

  • Package Name: org.springframework.boot:spring-boot-test
  • Package Type: Maven (Gradle)
  • Language: Java
  • Version: 4.0.0
  • Base Package: org.springframework.boot.test

Installation

Maven:

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-test</artifactId>
    <version>4.0.0</version>
    <scope>test</scope>
</dependency>

Gradle:

testImplementation 'org.springframework.boot:spring-boot-test:4.0.0'

Prerequisites

  • JUnit 5 (Jupiter): Required for most testing features
  • AssertJ: Required for assertions (provided transitively)
  • Spring Framework 6.2+: Core Spring testing support
  • Java 17+: Minimum Java version

Core Package Structure

org.springframework.boot.test
├── context          # Integration testing (@SpringBootTest, context runners)
├── json             # JSON testing (JacksonTester, GsonTester, JsonbTester)
├── system           # Output capture utilities
├── web              # Web testing utilities (HtmlUnit integration)
├── mock.web         # Mock servlet context
└── http.server      # Local test server utilities

Core Imports

// Integration Testing
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.TestConfiguration;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;

// Context Runners
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.boot.test.context.runner.WebApplicationContextRunner;
import org.springframework.boot.test.context.runner.ReactiveWebApplicationContextRunner;

// JSON Testing
import org.springframework.boot.test.json.JacksonTester;
import org.springframework.boot.test.json.GsonTester;
import org.springframework.boot.test.json.JsonbTester;
import org.springframework.boot.test.json.BasicJsonTester;
import org.springframework.boot.test.json.JsonContent;

// Output Capture
import org.springframework.boot.test.system.OutputCaptureExtension;
import org.springframework.boot.test.system.CapturedOutput;

// AssertJ Integration
import org.springframework.boot.test.context.assertj.AssertableApplicationContext;
import static org.assertj.core.api.Assertions.assertThat;

// Test Properties
import org.springframework.boot.test.util.TestPropertyValues;
import org.springframework.boot.test.util.ApplicationContextTestUtils;

// Test Configuration
import org.springframework.boot.test.context.FilteredClassLoader;

// Web Testing
import org.springframework.boot.test.http.server.LocalTestWebServer;
import org.springframework.boot.test.web.htmlunit.UriBuilderFactoryWebClient;
import org.springframework.boot.test.mock.web.SpringBootMockServletContext;

Basic Usage

Complete working example with all necessary imports and annotations:

package com.example.demo;

import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.beans.factory.annotation.Autowired;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;

@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
class MyApplicationTests {

    @Autowired
    private MyService myService;

    @Test
    void testServiceMethod() {
        String result = myService.process("test");
        assertThat(result).isEqualTo("processed: test");
    }
}

Feature Overview

Integration Testing

Full integration testing with complete Spring Boot application context, supporting multiple web environment modes and automatic configuration detection.

Key Classes:

  • @SpringBootTest - Main annotation for integration tests (since 1.4.0)
  • @LocalServerPort - Inject random server port (since 2.7.0)
  • @LocalManagementPort - Inject management server port (since 2.7.0)
  • @PropertyMapping - Map test annotation attributes to properties (since 4.0.0)
  • @TypeExcludeFilters - Register type exclude filters (since 4.0.0)

When to Use: Full application context testing with all auto-configurations

Package: org.springframework.boot.test.context

// Example usage:
@SpringBootTest(
    properties = {"spring.datasource.url=jdbc:h2:mem:testdb", "server.port=0"},
    args = {"--debug", "--spring.profiles.active=test"},
    classes = {MyTestConfiguration.class},
    webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT,
    useMainMethod = SpringBootTest.UseMainMethod.NEVER
)
class MyIntegrationTest { }

/**
 * Annotation for Spring Boot integration tests
 * Provides automatic SpringBootConfiguration detection, custom Environment properties,
 * application arguments, multiple web environment modes, and test context caching
 * @since 1.4.0
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@BootstrapWith(SpringBootTestContextBootstrapper.class)
@ExtendWith(SpringExtension.class)
public @interface SpringBootTest {
    /**
     * Alias for properties()
     * @return properties in key=value format
     */
    String[] value() default {};

    /**
     * Properties in key=value format to add to Environment
     * @return property definitions
     */
    String[] properties() default {};

    /**
     * Application arguments passed to the application
     * @return application arguments
     * @since 2.2.0
     */
    String[] args() default {};

    /**
     * Configuration classes for the application context.
     * If not specified, searches for @SpringBootConfiguration
     * @return configuration classes
     */
    Class<?>[] classes() default {};

    /**
     * Web environment mode for the test
     * @return the web environment mode
     */
    WebEnvironment webEnvironment() default WebEnvironment.MOCK;

    /**
     * Whether to use the application main method
     * @return main method usage mode
     * @since 3.0.0
     */
    UseMainMethod useMainMethod() default UseMainMethod.NEVER;

    /**
     * Web environment modes for integration tests
     */
    enum WebEnvironment {
        /** Mock web environment with MockMvc, no server started */
        MOCK,
        /** Start embedded server on random available port */
        RANDOM_PORT,
        /** Start embedded server on defined port from properties */
        DEFINED_PORT,
        /** No web environment, standard ApplicationContext */
        NONE;

        /**
         * Return if the environment uses an embedded web server
         * @return true for RANDOM_PORT and DEFINED_PORT
         */
        public boolean isEmbedded();
    }

    /**
     * Main method usage modes
     */
    enum UseMainMethod {
        /** Always use the main method */
        ALWAYS,
        /** Never use the main method */
        NEVER,
        /** Use main method when available */
        WHEN_AVAILABLE
    }
}

/**
 * Map test annotation attributes to properties
 * Indicates that attributes from a test annotation should be mapped into properties
 * Can be used at type level to define prefix, or on individual attributes to customize mapping
 * @since 4.0.0
 */
@Target({ ElementType.TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface PropertyMapping {
    /**
     * Property mapping prefix (type-level) or property name override (attribute-level)
     * @return the property mapping
     */
    String value() default "";

    /**
     * Controls when mapping should be skipped
     * @return skip mode
     */
    Skip skip() default Skip.NO;

    /**
     * Skip modes for property mapping
     */
    enum Skip {
        /** Skip mapping the property */
        YES,
        /** Skip mapping when default attribute value is specified */
        ON_DEFAULT_VALUE,
        /** Don't skip mapping */
        NO
    }
}

Context Runners

Lightweight application context testing without full application startup, ideal for testing auto-configurations and specific components in isolation.

Key Classes:

  • ApplicationContextRunner - Standard context testing (since 2.0.0)
  • WebApplicationContextRunner - Servlet web context testing (since 2.0.0)
  • ReactiveWebApplicationContextRunner - Reactive web context testing (since 2.0.0)

When to Use: Isolated component testing, auto-configuration testing, unit-style tests with minimal context

Package: org.springframework.boot.test.context.runner

// Example usage:
new ApplicationContextRunner()
    .withUserConfiguration(MyAutoConfiguration.class)
    .withPropertyValues("feature.enabled=true", "feature.timeout=5000")
    .withBean("myBean", MyService.class, () -> new MyServiceImpl())
    .run(context -> {
        assertThat(context).hasSingleBean(MyService.class);
        assertThat(context).hasBean("myBean");
    });

/**
 * Context runner for ApplicationContext
 * Provides fluent API for configuring and running an application context for tests
 * @since 2.0.0
 */
public final class ApplicationContextRunner
        extends AbstractApplicationContextRunner<ApplicationContextRunner, ConfigurableApplicationContext, AssertableApplicationContext> {

    /**
     * Create a new ApplicationContextRunner with default configuration
     */
    public ApplicationContextRunner();

    /**
     * Create with a custom supplier for the application context
     * @param contextFactory factory to create the application context
     */
    public ApplicationContextRunner(Supplier<ConfigurableApplicationContext> contextFactory);

    // Inherited from AbstractApplicationContextRunner:
    // - withUserConfiguration(Class<?>... classes)
    // - withConfiguration(Configurations configurations)
    // - withPropertyValues(String... pairs)
    // - withSystemProperties(String... pairs)
    // - withBean(String name, Class<T> type, Supplier<T> supplier, BeanDefinitionCustomizer... customizers)
    // - withInitializer(ApplicationContextInitializer<? super C> initializer)
    // - withClassLoader(ClassLoader classLoader)
    // - withParent(ApplicationContext parent)
    // - run(ContextConsumer<? super A> consumer)
    // - prepare(ContextConsumer<? super A> consumer)
}

// Example usage for web contexts:
new WebApplicationContextRunner()
    .withUserConfiguration(WebMvcConfig.class)
    .run(context -> assertThat(context).hasSingleBean(DispatcherServlet.class));

/**
 * Context runner for WebApplicationContext
 * @since 2.0.0
 */
public final class WebApplicationContextRunner
        extends AbstractApplicationContextRunner<WebApplicationContextRunner, ConfigurableWebApplicationContext, AssertableWebApplicationContext> {

    public WebApplicationContextRunner();

    public WebApplicationContextRunner(Supplier<ConfigurableWebApplicationContext> contextFactory);
}

// Example usage for reactive contexts:
new ReactiveWebApplicationContextRunner()
    .withUserConfiguration(WebFluxConfig.class)
    .run(context -> assertThat(context).hasSingleBean(DispatcherHandler.class));

/**
 * Context runner for ReactiveWebApplicationContext
 * @since 2.0.0
 */
public final class ReactiveWebApplicationContextRunner
        extends AbstractApplicationContextRunner<ReactiveWebApplicationContextRunner, ConfigurableReactiveWebApplicationContext, AssertableReactiveWebApplicationContext> {

    public ReactiveWebApplicationContextRunner();

    public ReactiveWebApplicationContextRunner(Supplier<ConfigurableReactiveWebApplicationContext> contextFactory);
}

JSON Testing

Comprehensive JSON serialization and deserialization testing with multiple library support (Jackson 3, Jackson 2, Gson, JSON-B) and extensive JSON path assertions.

Key Classes:

  • JacksonTester<T> - Jackson 3 testing (recommended, since 1.4.0, updated 4.0.0)
  • Jackson2Tester<T> - Jackson 2 testing (deprecated since 4.0.0, removed in 4.2.0)
  • GsonTester<T> - Gson testing (since 1.4.0)
  • JsonbTester<T> - JSON-B testing (since 2.0.0)
  • BasicJsonTester - Raw JSON string testing (since 1.4.0)
  • JsonContent<T> - JSON content wrapper with assertions (since 1.4.0)
  • ObjectContent<T> - Deserialized object wrapper (since 1.4.0)
  • JsonContentAssert - AssertJ assertions for JSON (since 1.4.0)

When to Use: Testing REST API JSON responses, verifying serialization/deserialization

Package: org.springframework.boot.test.json

// Example usage:
private JacksonTester<User> json;

@BeforeEach
void setup() {
    JacksonTester.initFields(this, JsonMapper.builder().build());
}

@Test
void testSerialization() throws Exception {
    User user = new User("alice", "alice@example.com");
    assertThat(json.write(user))
        .hasJsonPathStringValue("$.name", "alice")
        .extractingJsonPathStringValue("$.email")
        .isEqualTo("alice@example.com");
}

/**
 * AssertJ-based JSON tester backed by Jackson 3 (tools.jackson)
 * @param <T> the type under test
 * @since 1.4.0 (updated for Jackson 3 in 4.0.0)
 */
public class JacksonTester<T> extends AbstractJsonMarshalTester<T> {

    /**
     * Create a new uninitialized JacksonTester instance
     * @param jsonMapper the Jackson JSON mapper
     * @since 4.0.0
     */
    protected JacksonTester(JsonMapper jsonMapper);

    /**
     * Create a new JacksonTester instance
     * @param resourceLoadClass the source class used to load resources
     * @param type the type under test
     * @param jsonMapper the Jackson JSON mapper
     * @since 4.0.0
     */
    public JacksonTester(Class<?> resourceLoadClass, ResolvableType type, JsonMapper jsonMapper);

    /**
     * Create a new JacksonTester instance with JSON view support
     * @param resourceLoadClass the source class used to load resources
     * @param type the type under test
     * @param jsonMapper the Jackson JSON mapper
     * @param view the JSON view class
     */
    public JacksonTester(Class<?> resourceLoadClass, ResolvableType type, JsonMapper jsonMapper, Class<?> view);

    /**
     * Initialize all JacksonTester fields in a test instance
     * Uses reflection to find and initialize all JacksonTester fields
     * @param testInstance the test instance
     * @param jsonMapper the Jackson JSON mapper
     */
    public static void initFields(Object testInstance, JsonMapper jsonMapper);

    /**
     * Initialize all JacksonTester fields using a mapper factory
     * @param testInstance the test instance
     * @param jsonMapperFactory factory to create the JSON mapper
     */
    public static void initFields(Object testInstance, ObjectFactory<JsonMapper> jsonMapperFactory);

    /**
     * Create a new tester instance with a specific JSON view
     * @param view the JSON view class
     * @return new JacksonTester instance configured with the view
     */
    public JacksonTester<T> forView(Class<?> view);

    // Inherits from AbstractJsonMarshalTester:
    // - JsonContent<T> write(T value) throws IOException
    // - T parseObject(String jsonString) throws IOException
    // - T parseObject(byte[] jsonBytes) throws IOException
    // - ObjectContent<T> parse(String jsonString) throws IOException
    // - ObjectContent<T> parse(byte[] jsonBytes) throws IOException
    // - T readObject(String resourcePath) throws IOException
    // - T readObject(File file) throws IOException
    // - T readObject(InputStream inputStream) throws IOException
    // - ObjectContent<T> read(String resourcePath) throws IOException
    // - ObjectContent<T> read(File file) throws IOException
    // - ObjectContent<T> read(InputStream inputStream) throws IOException
}

/**
 * JSON content wrapper with AssertJ assertion support
 * @param <T> the source type that created the content
 * @since 1.4.0
 */
public final class JsonContent<T> implements AssertProvider<JsonContentAssert> {

    /**
     * Create a new JsonContent instance
     * @param resourceLoadClass the source class used to load resources
     * @param type the type under test (or null if not known)
     * @param json the actual JSON content
     */
    public JsonContent(Class<?> resourceLoadClass, ResolvableType type, String json);

    /**
     * Get the actual JSON content string
     * @return the JSON content
     */
    public String getJson();

    /**
     * Get AssertJ assertions for this content
     * @return JsonContentAssert instance
     * @deprecated since 1.5.7, use AssertJ's assertThat(jsonContent) instead
     */
    @Deprecated(since = "1.5.7", forRemoval = false)
    public JsonContentAssert assertThat();
}

/**
 * AssertJ assertions for JSON content validation
 * @since 1.4.0
 */
public class JsonContentAssert extends AbstractAssert<JsonContentAssert, CharSequence> {

    // Lenient equality assertions (ignores array order, extensible objects)
    public JsonContentAssert isEqualToJson(CharSequence expected);
    public JsonContentAssert isEqualToJson(String path, Class<?> resourceLoadClass);
    public JsonContentAssert isEqualToJson(byte[] expected);
    public JsonContentAssert isEqualToJson(File expected);
    public JsonContentAssert isEqualToJson(InputStream expected);
    public JsonContentAssert isEqualToJson(Resource expected);

    // Strict equality assertions (enforces order, exact structure)
    public JsonContentAssert isStrictlyEqualToJson(CharSequence expected);
    public JsonContentAssert isStrictlyEqualToJson(byte[] expected);
    public JsonContentAssert isStrictlyEqualToJson(File expected);

    // JSON path existence assertions
    public JsonContentAssert hasJsonPath(CharSequence expression, Object... args);
    public JsonContentAssert hasJsonPathValue(CharSequence expression, Object... args);
    public JsonContentAssert doesNotHaveJsonPath(CharSequence expression, Object... args);

    // JSON path type assertions
    public JsonContentAssert hasJsonPathStringValue(CharSequence expression, Object... args);
    public JsonContentAssert hasJsonPathNumberValue(CharSequence expression, Object... args);
    public JsonContentAssert hasJsonPathBooleanValue(CharSequence expression, Object... args);
    public JsonContentAssert hasJsonPathArrayValue(CharSequence expression, Object... args);
    public JsonContentAssert hasJsonPathMapValue(CharSequence expression, Object... args);

    // JSON path value extraction (returns typed assertions for chaining)
    public AbstractObjectAssert<?, Object> extractingJsonPathValue(CharSequence expression, Object... args);
    public AbstractCharSequenceAssert<?, String> extractingJsonPathStringValue(CharSequence expression, Object... args);
    public AbstractObjectAssert<?, Number> extractingJsonPathNumberValue(CharSequence expression, Object... args);
    public AbstractBooleanAssert<?> extractingJsonPathBooleanValue(CharSequence expression, Object... args);
    public <E> ListAssert<E> extractingJsonPathArrayValue(CharSequence expression, Object... args);
    public <K, V> MapAssert<K, V> extractingJsonPathMapValue(CharSequence expression, Object... args);
}

// Example chained assertions:
assertThat(jsonContent)
    .hasJsonPath("$.users[*].name")
    .hasJsonPathArrayValue("$.users")
    .extractingJsonPathStringValue("$.users[0].email")
    .startsWith("user")
    .endsWith("@example.com");

AssertJ Integration

Rich assertions for validating application contexts, beans, and context startup failures with fluent AssertJ API.

Key Interfaces:

  • AssertableApplicationContext - Context with assertions (since 2.0.0)
  • ApplicationContextAssert<C> - Context assertion methods (since 2.0.0)
  • AssertableWebApplicationContext - Web context assertions (since 2.0.0)
  • AssertableReactiveWebApplicationContext - Reactive context assertions (since 2.0.0)

When to Use: Asserting on beans, context state, startup failures in context runner tests

Package: org.springframework.boot.test.context.assertj

// Example usage with context runners:
new ApplicationContextRunner()
    .withUserConfiguration(DataSourceConfig.class)
    .run(context -> {
        assertThat(context).hasSingleBean(DataSource.class);
        assertThat(context).hasBean("dataSource");
        assertThat(context).getBean(DataSource.class)
            .isInstanceOf(HikariDataSource.class);
        assertThat(context).getBeans(DataSource.class)
            .hasSize(1)
            .containsKey("dataSource");
    });

// Example testing for context failure:
new ApplicationContextRunner()
    .withUserConfiguration(InvalidConfig.class)
    .run(context -> {
        assertThat(context).hasFailed();
        assertThat(context).getFailure()
            .isInstanceOf(BeanCreationException.class)
            .hasMessageContaining("Could not create bean");
    });

/**
 * ApplicationContext that can be used with AssertJ assertions
 * @since 2.0.0
 */
public interface AssertableApplicationContext extends ConfigurableApplicationContext, AssertProvider<ApplicationContextAssert<ApplicationContext>> {

    /**
     * Return AssertJ assertions for this context
     * @return ApplicationContextAssert instance
     */
    ApplicationContextAssert<ApplicationContext> assertThat();

    /**
     * Get the startup failure if the context failed to load
     * @return the startup failure or null if context started successfully
     */
    Throwable getStartupFailure();
}

/**
 * AssertJ assertions for ApplicationContext
 * @param <C> the application context type
 * @since 2.0.0
 */
public class ApplicationContextAssert<C extends ApplicationContext> extends AbstractAssert<ApplicationContextAssert<C>, C> {

    /**
     * Verify context has a bean with the given name
     * @param name the bean name
     * @return this assertion object
     */
    public ApplicationContextAssert<C> hasBean(String name);

    /**
     * Verify context has a single bean of the given type
     * @param type the bean type
     * @return this assertion object
     */
    public ApplicationContextAssert<C> hasSingleBean(Class<?> type);

    /**
     * Verify context does not have a bean of the given type
     * @param type the bean type
     * @return this assertion object
     */
    public ApplicationContextAssert<C> doesNotHaveBean(Class<?> type);

    /**
     * Verify context does not have a bean with the given name
     * @param name the bean name
     * @return this assertion object
     */
    public ApplicationContextAssert<C> doesNotHaveBean(String name);

    /**
     * Extract bean for further assertions
     * @param name the bean name
     * @return ObjectAssert for the bean
     */
    public AbstractObjectAssert<?, Object> getBean(String name);

    /**
     * Extract bean of specific type for further assertions
     * @param type the bean type
     * @param <T> the bean type
     * @return ObjectAssert for the bean
     */
    public <T> AbstractObjectAssert<?, T> getBean(Class<T> type);

    /**
     * Extract bean of specific type with name for further assertions
     * @param name the bean name
     * @param type the bean type
     * @param <T> the bean type
     * @return ObjectAssert for the bean
     */
    public <T> AbstractObjectAssert<?, T> getBean(String name, Class<T> type);

    /**
     * Get all beans of a given type
     * @param type the bean type
     * @param <T> the bean type
     * @return MapAssert for name to bean mappings
     */
    public <T> MapAssert<String, T> getBeans(Class<T> type);

    /**
     * Verify context failed to start
     * @return this assertion object
     */
    public ApplicationContextAssert<C> hasFailed();

    /**
     * Extract the startup failure for further assertions
     * @return ThrowableAssert for the failure
     */
    public AbstractThrowableAssert<?, ? extends Throwable> getFailure();
}

Output Capture

Capture and verify System.out and System.err output during test execution.

Key Classes:

  • OutputCaptureExtension - JUnit 5 extension (since 2.2.0)
  • CapturedOutput - Interface for captured output (since 2.2.0)
  • OutputCaptureRule - JUnit 4 rule (deprecated since 2.2.0)

When to Use: Verifying logging output, console messages, error output

Package: org.springframework.boot.test.system

// Example usage:
@ExtendWith(OutputCaptureExtension.class)
class MyTest {

    @Test
    void captureSystemOut(CapturedOutput output) {
        System.out.println("Hello World");
        System.err.println("Error message");

        assertThat(output.getOut()).contains("Hello World");
        assertThat(output.getErr()).contains("Error message");
        assertThat(output.getAll()).contains("Hello World", "Error message");
        assertThat(output).contains("Hello"); // CapturedOutput is CharSequence
    }
}

/**
 * JUnit 5 Extension to capture System.out and System.err
 * @since 2.2.0
 */
public class OutputCaptureExtension implements BeforeEachCallback, AfterEachCallback, ParameterResolver {

    /**
     * Resolve CapturedOutput parameter for test methods
     * @param parameterContext the parameter context
     * @param extensionContext the extension context
     * @return true if parameter is CapturedOutput
     */
    @Override
    public boolean supportsParameter(ParameterContext parameterContext, ExtensionContext extensionContext);

    /**
     * Resolve the CapturedOutput instance
     * @param parameterContext the parameter context
     * @param extensionContext the extension context
     * @return the CapturedOutput instance
     */
    @Override
    public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext);
}

/**
 * Interface for accessing captured output
 * @since 2.2.0
 */
public interface CapturedOutput extends CharSequence {

    /**
     * Get all captured output (both stdout and stderr)
     * @return the complete captured output
     */
    String getAll();

    /**
     * Get captured stdout output only
     * @return stdout content
     */
    String getOut();

    /**
     * Get captured stderr output only
     * @return stderr content
     */
    String getErr();

    // Inherits from CharSequence:
    // - int length()
    // - char charAt(int index)
    // - CharSequence subSequence(int start, int end)
    // - String toString()
}

Test Configuration

Define test-specific bean configurations and components for focused test environments, and simulate classloading scenarios with filtered classloaders.

Key Classes:

  • @TestConfiguration - Test-specific configuration (since 1.4.0)
  • @TestComponent - Test-only component (since 1.4.0)
  • FilteredClassLoader - Test classloader for simulating missing dependencies (since 2.0.0)

When to Use: Overriding beans for tests, adding test-specific beans, testing conditional auto-configurations

Package: org.springframework.boot.test.context

// Example usage as nested configuration:
@SpringBootTest
class MyIntegrationTest {

    @TestConfiguration
    static class TestConfig {
        @Bean
        @Primary
        DataSource testDataSource() {
            return new EmbeddedDatabaseBuilder()
                .setType(EmbeddedDatabaseType.H2)
                .build();
        }
    }

    @Autowired
    private DataSource dataSource; // Gets testDataSource bean
}

// Example usage as separate class:
@TestConfiguration(proxyBeanMethods = false)
public class MockServiceConfiguration {

    @Bean
    public ExternalService externalService() {
        return Mockito.mock(ExternalService.class);
    }
}

// Import in test:
@SpringBootTest
@Import(MockServiceConfiguration.class)
class ServiceTest { }

/**
 * Configuration that can be imported or used as nested configuration
 * Does not trigger component scanning or prevent @SpringBootConfiguration detection
 * @since 1.4.0
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Configuration
public @interface TestConfiguration {

    /**
     * Explicitly specify the name of the Spring bean definition
     * @return the bean name
     */
    String value() default "";

    /**
     * Specify whether @Bean methods should get proxied
     * @return true to use proxies (default), false for lite mode
     */
    boolean proxyBeanMethods() default true;
}

/**
 * Stereotyp annotation for test components
 * Excluded from component scans unless explicitly included
 * @since 1.4.0
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Component
public @interface TestComponent {

    /**
     * The value may indicate a suggestion for a logical component name
     * @return the suggested component name, if any
     */
    String value() default "";
}

Test Property Management

Utilities for managing test-specific properties, environment variables, and system properties.

Key Classes:

  • TestPropertyValues - Fluent property management (since 2.0.0)

When to Use: Setting properties for context runner tests, temporary property override

Package: org.springframework.boot.test.util

// Example usage with context runners:
new ApplicationContextRunner()
    .withInitializer(context ->
        TestPropertyValues.of(
            "app.name=TestApp",
            "app.timeout=5000",
            "app.debug=true"
        ).applyTo(context))
    .run(context -> {
        assertThat(context.getEnvironment().getProperty("app.name"))
            .isEqualTo("TestApp");
    });

// Example with fluent API:
TestPropertyValues.of("prop1=value1")
    .and("prop2=value2", "prop3=value3")
    .applyTo(context);

// Example with system properties:
String result = TestPropertyValues
    .of("java.io.tmpdir=/custom/tmp")
    .applyToSystemProperties(() -> {
        // Code that uses system properties
        return System.getProperty("java.io.tmpdir");
    });
assertThat(result).isEqualTo("/custom/tmp");

/**
 * Utility for managing test-specific property values
 * @since 2.0.0
 */
public final class TestPropertyValues {

    /**
     * Create instance from name=value pairs
     * @param pairs property pairs in key=value format
     * @return TestPropertyValues instance
     */
    public static TestPropertyValues of(String... pairs);

    /**
     * Create instance from a map
     * @param map map of property names to values
     * @return TestPropertyValues instance
     */
    public static TestPropertyValues of(Map<String, String> map);

    /**
     * Create instance from an iterable of name=value pairs
     * @param pairs iterable of property pairs
     * @return TestPropertyValues instance
     */
    public static TestPropertyValues of(Iterable<String> pairs);

    /**
     * Create empty instance
     * @return empty TestPropertyValues
     */
    public static TestPropertyValues empty();

    /**
     * Add additional property values
     * @param pairs additional property pairs
     * @return new TestPropertyValues with added properties
     */
    public TestPropertyValues and(String... pairs);

    /**
     * Apply properties to an ApplicationContext
     * @param context the context to configure
     */
    public void applyTo(ConfigurableApplicationContext context);

    /**
     * Apply properties to an Environment
     * @param environment the environment to configure
     */
    public void applyTo(ConfigurableEnvironment environment);

    /**
     * Apply properties to an Environment with specific property source name
     * @param environment the environment to configure
     * @param name the name of the property source
     */
    public void applyTo(ConfigurableEnvironment environment, TestPropertyValues.Type type, String name);

    /**
     * Apply properties to system properties
     * @param action action to perform with system properties set
     * @param <T> return type
     * @return result of the action
     */
    public <T> T applyToSystemProperties(Supplier<T> action);

    /**
     * Property source type
     */
    public enum Type {
        /** Map property source */
        MAP,
        /** System environment property source */
        SYSTEM_ENVIRONMENT
    }
}

Web Test Utilities

HtmlUnit integration, local test web server utilities, and mock servlet context support for web application testing.

Key Classes:

  • LocalTestWebServer - Test server information (since 4.0.0)
  • UriBuilderFactoryWebClient - HtmlUnit client (since 4.0.0)
  • UriBuilderFactoryWebConnectionHtmlUnitDriver - Selenium driver (since 4.0.0)
  • SpringBootMockServletContext - Mock servlet context (since 1.4.0)

When to Use: End-to-end web testing, HtmlUnit-based UI testing

Package: org.springframework.boot.test.http.server, org.springframework.boot.test.web.htmlunit, org.springframework.boot.test.mock.web

// Example usage with @SpringBootTest:
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
class WebIntegrationTest {

    @Autowired
    private ApplicationContext context;

    @Test
    void testWithLocalTestWebServer() {
        LocalTestWebServer server = LocalTestWebServer.obtain(context);

        String baseUri = server.uri(); // "http://localhost:8080"
        String apiUri = server.uri("/api/users"); // "http://localhost:8080/api/users"

        RestTemplate restTemplate = new RestTemplate();
        ResponseEntity<String> response = restTemplate.getForEntity(apiUri, String.class);
        assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
    }
}

// Example with HtmlUnit WebClient:
LocalTestWebServer server = LocalTestWebServer.of(Scheme.HTTP, 8080);
UriBuilderFactoryWebClient client = new UriBuilderFactoryWebClient(server.uriBuilderFactory());

HtmlPage page = client.getPage("/index.html");
assertThat(page.getTitleText()).isEqualTo("Welcome");

/**
 * Information about a local test web server
 * @since 4.0.0
 */
public final class LocalTestWebServer {

    /**
     * Get the scheme (HTTP or HTTPS)
     * @return the scheme
     */
    public Scheme scheme();

    /**
     * Get the base URI for this server
     * @return the base URI (e.g., "http://localhost:8080")
     */
    public String uri();

    /**
     * Get a URI with the given path
     * @param uri the path to append
     * @return the complete URI
     */
    public String uri(String uri);

    /**
     * Get a URI builder for the given path
     * @param uri the path
     * @return UriBuilder instance
     */
    public UriBuilder uriBuilder(String uri);

    /**
     * Get a URI builder factory for this server
     * @return UriBuilderFactory instance
     */
    public UriBuilderFactory uriBuilderFactory();

    /**
     * Create a new LocalTestWebServer with a different path
     * @param path the new path
     * @return new LocalTestWebServer instance
     */
    public LocalTestWebServer withPath(String path);

    /**
     * Create from scheme and port
     * @param scheme the scheme (HTTP or HTTPS)
     * @param port the port number
     * @return LocalTestWebServer instance
     */
    public static LocalTestWebServer of(Scheme scheme, int port);

    /**
     * Create from scheme, port, and context path
     * @param scheme the scheme
     * @param port the port number
     * @param contextPath the context path
     * @return LocalTestWebServer instance
     */
    public static LocalTestWebServer of(Scheme scheme, int port, String contextPath);

    /**
     * Obtain from an ApplicationContext
     * @param applicationContext the application context
     * @return LocalTestWebServer instance
     * @throws IllegalStateException if no local test web server is available
     */
    public static LocalTestWebServer obtain(ApplicationContext applicationContext);

    /**
     * Get the LocalTestWebServer from an ApplicationContext
     * @param applicationContext the application context
     * @return LocalTestWebServer instance or null if not available
     */
    public static LocalTestWebServer get(ApplicationContext applicationContext);

    /**
     * Create from scheme and base URI details supplier
     * @param scheme the scheme
     * @param baseUriDetailsSupplier supplier for base URI details
     * @return LocalTestWebServer instance
     */
    public static LocalTestWebServer of(Scheme scheme, Supplier<BaseUriDetails> baseUriDetailsSupplier);

    /**
     * Details of the base URI to the local test web server
     */
    public record BaseUriDetails(int port, String path) {
        /**
         * Get the URI for the given scheme
         * @param scheme the scheme
         * @return the URI string
         */
        String uri(Scheme scheme);

        /**
         * Create new BaseUriDetails with appended path
         * @param path the path to append
         * @return new BaseUriDetails instance
         */
        BaseUriDetails withPath(String path);
    }

    /**
     * Server scheme enumeration
     */
    public enum Scheme {
        /** HTTP scheme */
        HTTP,
        /** HTTPS scheme */
        HTTPS
    }

    /**
     * Internal strategy to provide the running LocalTestWebServer
     * Implementations registered in spring.factories
     */
    @FunctionalInterface
    public interface Provider {
        /**
         * Return the provided LocalTestWebServer or null
         * @return the local test web server or null
         */
        LocalTestWebServer getLocalTestWebServer();
    }
}

/**
 * HtmlUnit WebClient configured with UriBuilderFactory
 * @since 4.0.0
 */
public class UriBuilderFactoryWebClient extends WebClient {

    /**
     * Create with UriBuilderFactory
     * @param uriBuilderFactory the URI builder factory
     */
    public UriBuilderFactoryWebClient(UriBuilderFactory uriBuilderFactory);

    /**
     * Get a page using a relative URL
     * @param url the relative URL
     * @param <P> the page type
     * @return the page
     * @throws IOException on error
     */
    @Override
    public <P extends Page> P getPage(String url) throws IOException;
}

/**
 * Mock ServletContext for Spring Boot applications
 * @since 1.4.0
 */
public class SpringBootMockServletContext extends MockServletContext {

    /**
     * Create with resource base path
     * @param resourceBasePath the base path for resources
     */
    public SpringBootMockServletContext(String resourceBasePath);

    /**
     * Create with resource base path and resource loader
     * @param resourceBasePath the base path for resources
     * @param resourceLoader the resource loader
     */
    public SpringBootMockServletContext(String resourceBasePath, ResourceLoader resourceLoader);
}

Quick Reference: Choosing the Right Testing Approach

ScenarioRecommended ApproachKey Classes
Full integration test with web server@SpringBootTest with RANDOM_PORTSpringBootTest, LocalTestWebServer
Test auto-configuration in isolationContext runnersApplicationContextRunner
Test JSON serializationJSON testersJacksonTester, GsonTester
Test with minimal contextContext runners with specific configApplicationContextRunner.withUserConfiguration()
Verify logging outputOutput captureOutputCaptureExtension, CapturedOutput
Test-specific bean overrides@TestConfigurationTestConfiguration, TestComponent
Web UI testing with HtmlUnitWeb test utilitiesUriBuilderFactoryWebClient
Temporary test propertiesTest property valuesTestPropertyValues

Common Patterns

Pattern 1: Integration Test with Random Port

import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
import org.springframework.boot.test.http.server.LocalTestWebServer;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.web.client.RestTemplate;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;

@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
class IntegrationTest {

    @Autowired
    private ApplicationContext context;

    @Test
    void testEndpoint() {
        LocalTestWebServer server = LocalTestWebServer.obtain(context);
        RestTemplate restTemplate = new RestTemplate();
        String response = restTemplate.getForObject(server.uri("/api/test"), String.class);
        assertThat(response).isNotNull();
    }
}

Pattern 2: Context Runner for Auto-Configuration Testing

import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;

class AutoConfigTest {

    private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
        .withUserConfiguration(MyAutoConfiguration.class);

    @Test
    void whenConditionMet_beanIsCreated() {
        contextRunner
            .withPropertyValues("feature.enabled=true")
            .run(context -> assertThat(context).hasSingleBean(FeatureBean.class));
    }
}

Pattern 3: JSON Testing

import org.springframework.boot.test.json.JacksonTester;
import tools.jackson.databind.json.JsonMapper;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;

class JsonTest {

    private JacksonTester<User> json;

    @BeforeEach
    void setup() {
        JacksonTester.initFields(this, JsonMapper.builder().build());
    }

    @Test
    void testSerialization() throws Exception {
        User user = new User("john", "john@example.com");
        assertThat(json.write(user))
            .hasJsonPathStringValue("$.name")
            .extractingJsonPathStringValue("$.email")
            .isEqualTo("john@example.com");
    }
}

Pattern 4: Output Capture

import org.springframework.boot.test.system.OutputCaptureExtension;
import org.springframework.boot.test.system.CapturedOutput;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import static org.assertj.core.api.Assertions.assertThat;

@ExtendWith(OutputCaptureExtension.class)
class OutputTest {

    @Test
    void testLogging(CapturedOutput output) {
        System.out.println("Test message");
        assertThat(output).contains("Test message");
    }
}

Migration Notes

From Spring Boot 3.x to 4.0

Jackson 3 Migration (Critical)

Spring Boot 4.0 introduces Jackson 3 support while deprecating Jackson 2 APIs.

  1. Tester Class Migration:

    // Old (Spring Boot 3.x with Jackson 2)
    import com.fasterxml.jackson.databind.ObjectMapper;
    import org.springframework.boot.test.json.Jackson2Tester;
    
    private Jackson2Tester<User> json;
    
    @BeforeEach
    void setup() {
        ObjectMapper mapper = new ObjectMapper();
        Jackson2Tester.initFields(this, mapper);
    }
    
    // New (Spring Boot 4.0 with Jackson 3)
    import tools.jackson.databind.json.JsonMapper;
    import org.springframework.boot.test.json.JacksonTester;
    
    private JacksonTester<User> json;
    
    @BeforeEach
    void setup() {
        JsonMapper mapper = JsonMapper.builder().build();
        JacksonTester.initFields(this, mapper);
    }
  2. Package Changes:

    • com.fasterxml.jackson.*tools.jackson.*
    • ObjectMapperJsonMapper
    • Module paths change: com.fasterxml.jackson.datatype.jsr310.JavaTimeModuletools.jackson.datatype.jsr310.JavaTimeModule
  3. Configuration Pattern Changes:

    // Old (Jackson 2)
    ObjectMapper mapper = new ObjectMapper();
    mapper.registerModule(new JavaTimeModule());
    mapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
    mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
    
    // New (Jackson 3)
    JsonMapper mapper = JsonMapper.builder()
        .addModule(new JavaTimeModule())
        .configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false)
        .serializationInclusion(JsonInclude.Include.NON_NULL)
        .build();
  4. Migration Timeline:

    • Spring Boot 4.0 (current): Jackson2Tester deprecated
    • Spring Boot 4.2 (planned): Jackson2Tester removed
    • Recommendation: Migrate immediately to avoid breaking changes

JUnit 4 to JUnit 5 Migration

OutputCaptureRule (JUnit 4) deprecated - use OutputCaptureExtension (JUnit 5):

// Old (JUnit 4)
import org.junit.Rule;
import org.springframework.boot.test.rule.OutputCaptureRule;

public class MyTest {
    @Rule
    public OutputCaptureRule output = new OutputCaptureRule();

    @Test
    public void test() {
        System.out.println("message");
        assertThat(output.toString()).contains("message");
    }
}

// New (JUnit 5)
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.boot.test.system.OutputCaptureExtension;
import org.springframework.boot.test.system.CapturedOutput;

@ExtendWith(OutputCaptureExtension.class)
class MyTest {

    @Test
    void test(CapturedOutput output) {
        System.out.println("message");
        assertThat(output).contains("message");
    }
}

New Annotations in 4.0

  1. @PropertyMapping: Map test annotation attributes to environment properties
  2. @TypeExcludeFilters: Register TypeExcludeFilter classes for component scanning control

See Integration Testing for detailed usage.

Troubleshooting

Common Issues

Issue: NoSuchBeanDefinitionException in @SpringBootTest

  • Cause: Missing @SpringBootApplication or component scan configuration
  • Solution: Ensure test class is in same package or subpackage as @SpringBootApplication

Issue: Context runner test fails to load expected beans

  • Cause: Missing auto-configuration in withUserConfiguration()
  • Solution: Include all required configuration classes explicitly

Issue: JSON tester fields are null

  • Cause: Forgot to call initFields() in @BeforeEach
  • Solution: Add JacksonTester.initFields(this, mapper) in setup method

Issue: Output capture doesn't capture logs

  • Cause: Logging framework configuration redirects output
  • Solution: Ensure logging outputs to System.out/System.err

Issue: Random port not injected

  • Cause: Wrong WebEnvironment mode
  • Solution: Use webEnvironment = WebEnvironment.RANDOM_PORT

See Also

  • Spring Framework Testing Documentation
  • Spring Boot Testing Features
  • AssertJ Documentation
  • JUnit 5 User Guide

Version History

  • 4.0.0: Jackson 3 support, JUnit 4 deprecation, new annotations
  • 3.x: Previous stable version with Jackson 2

docs

assertj-integration.md

context-runners.md

index.md

integration-testing.md

json-testing.md

output-capture.md

test-configuration.md

test-properties.md

web-test-utilities.md

tile.json