or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

assertj-integration.mdcontext-runners.mdindex.mdintegration-testing.mdjson-testing.mdoutput-capture.mdtest-configuration.mdtest-properties.mdweb-test-utilities.md
tile.json

assertj-integration.mddocs/

AssertJ Integration for Context and Bean Assertions

Rich AssertJ-based assertions for validating application contexts, beans, and context startup failures.

Package

org.springframework.boot.test.context.assertj

Prerequisites

  • AssertJ (provided transitively)
  • Context runner or assertable context

Core Imports

import org.springframework.boot.test.context.assertj.ApplicationContextAssertProvider;
import org.springframework.boot.test.context.assertj.AssertableApplicationContext;
import org.springframework.boot.test.context.assertj.AssertableWebApplicationContext;
import org.springframework.boot.test.context.assertj.ApplicationContextAssert;
import org.springframework.boot.test.context.assertj.ApplicationContextAssert.Scope;
import static org.assertj.core.api.Assertions.assertThat;

ApplicationContextAssertProvider

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

Base interface for application contexts that provide AssertJ assertion support. This interface extends ApplicationContext, AssertProvider, and Closeable, serving as the foundation for all assertable context types.

/**
 * Base interface for application contexts that provide AssertJ assertion support
 * @param <C> the application context type
 * @since 2.0.0
 */
public interface ApplicationContextAssertProvider<C extends ApplicationContext>
        extends ApplicationContext, AssertProvider<ApplicationContextAssert<C>>, Closeable {

    /**
     * Return an assert for AssertJ
     * @return an AssertJ assert
     * @deprecated since 2.0.0 - to prevent accidental use. Prefer standard AssertJ assertThat(context) calls instead
     */
    @Deprecated(since = "2.0.0", forRemoval = false)
    @Override
    ApplicationContextAssert<C> assertThat();

    /**
     * Return the original source ApplicationContext
     * @return the source application context
     * @throws IllegalStateException if the source context failed to start
     */
    C getSourceApplicationContext();

    /**
     * Return the original source ApplicationContext, casting it to the requested type
     * @param <T> the context type
     * @param requiredType the required context type
     * @return the source application context
     * @throws IllegalStateException if the source context failed to start
     */
    <T extends C> T getSourceApplicationContext(Class<T> requiredType);

    /**
     * Return the failure that caused application context to fail or null if the context started without issue
     * @return the startup failure or null
     */
    Throwable getStartupFailure();

    /**
     * Close the context
     */
    @Override
    void close();

    /**
     * Factory method to create a new ApplicationContextAssertProvider instance
     * @param <T> the assert provider type
     * @param <C> the context type
     * @param type the type of ApplicationContextAssertProvider required (must be an interface)
     * @param contextType the type of ApplicationContext being managed (must be an interface)
     * @param contextSupplier a supplier that will either return a fully configured ApplicationContext or throw an exception if the context fails to start
     * @return an ApplicationContextAssertProvider instance
     */
    static <T extends ApplicationContextAssertProvider<C>, C extends ApplicationContext> T get(
            Class<T> type,
            Class<? extends C> contextType,
            Supplier<? extends C> contextSupplier);

    /**
     * Factory method to create a new ApplicationContextAssertProvider instance with additional context interfaces
     * @param <T> the assert provider type
     * @param <C> the context type
     * @param type the type of ApplicationContextAssertProvider required (must be an interface)
     * @param contextType the type of ApplicationContext being managed (must be an interface)
     * @param contextSupplier a supplier that will either return a fully configured ApplicationContext or throw an exception if the context fails to start
     * @param additionalContextInterfaces any additional context interfaces to add to the proxy
     * @return an ApplicationContextAssertProvider instance
     * @since 3.4.0
     */
    static <T extends ApplicationContextAssertProvider<C>, C extends ApplicationContext> T get(
            Class<T> type,
            Class<? extends C> contextType,
            Supplier<? extends C> contextSupplier,
            Class<?>... additionalContextInterfaces);
}

AssertableApplicationContext

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

ApplicationContext that provides AssertJ assertions support.

public interface AssertableApplicationContext
        extends ApplicationContextAssertProvider<ConfigurableApplicationContext>,
                ConfigurableApplicationContext {

    /**
     * Factory method to create an AssertableApplicationContext
     * @param contextSupplier supplier for the application context
     * @return AssertableApplicationContext instance
     * @since 2.0.0
     */
    static AssertableApplicationContext get(Supplier<? extends ConfigurableApplicationContext> contextSupplier);

    /**
     * Factory method to create an AssertableApplicationContext with additional context interfaces
     * @param contextSupplier supplier for the application context
     * @param additionalContextInterfaces any additional context interfaces to add to the proxy
     * @return AssertableApplicationContext instance
     * @since 3.4.0
     */
    static AssertableApplicationContext get(Supplier<? extends ConfigurableApplicationContext> contextSupplier, Class<?>... additionalContextInterfaces);
}

AssertableWebApplicationContext

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

WebApplicationContext that provides AssertJ assertions support.

public interface AssertableWebApplicationContext
        extends ApplicationContextAssertProvider<ConfigurableWebApplicationContext>,
                ConfigurableWebApplicationContext {

    /**
     * Factory method to create an AssertableWebApplicationContext
     * @param contextSupplier supplier for the web application context
     * @return AssertableWebApplicationContext instance
     * @since 2.0.0
     */
    static AssertableWebApplicationContext get(Supplier<? extends ConfigurableWebApplicationContext> contextSupplier);

    /**
     * Factory method to create an AssertableWebApplicationContext with additional context interfaces
     * @param contextSupplier supplier for the web application context
     * @param additionalContextInterfaces any additional context interfaces to add to the proxy
     * @return AssertableWebApplicationContext instance
     * @since 3.4.0
     */
    static AssertableWebApplicationContext get(Supplier<? extends ConfigurableWebApplicationContext> contextSupplier, Class<?>... additionalContextInterfaces);
}

AssertableReactiveWebApplicationContext

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

ReactiveWebApplicationContext that provides AssertJ assertions support.

public interface AssertableReactiveWebApplicationContext
        extends ApplicationContextAssertProvider<ConfigurableReactiveWebApplicationContext>,
                ConfigurableReactiveWebApplicationContext {

    /**
     * Factory method to create an AssertableReactiveWebApplicationContext
     * @param contextSupplier supplier for the reactive web application context
     * @return AssertableReactiveWebApplicationContext instance
     * @since 2.0.0
     */
    static AssertableReactiveWebApplicationContext get(Supplier<? extends ConfigurableReactiveWebApplicationContext> contextSupplier);

    /**
     * Factory method to create an AssertableReactiveWebApplicationContext with additional context interfaces
     * @param contextSupplier supplier for the reactive web application context
     * @param additionalContextInterfaces any additional context interfaces to add to the proxy
     * @return AssertableReactiveWebApplicationContext instance
     * @since 3.4.0
     */
    static AssertableReactiveWebApplicationContext get(Supplier<? extends ConfigurableReactiveWebApplicationContext> contextSupplier, Class<?>... additionalContextInterfaces);
}

ApplicationContextAssert

Full Package: org.springframework.boot.test.context.assertj.ApplicationContextAssert<C>

Fluent assertions for ApplicationContext testing.

public class ApplicationContextAssert<C extends ApplicationContext> {

    // Bean existence
    ApplicationContextAssert<C> hasBean(String name);
    ApplicationContextAssert<C> hasSingleBean(Class<?> type);
    ApplicationContextAssert<C> hasSingleBean(Class<?> type, Scope scope);
    ApplicationContextAssert<C> doesNotHaveBean(Class<?> type);
    ApplicationContextAssert<C> doesNotHaveBean(Class<?> type, Scope scope);
    ApplicationContextAssert<C> doesNotHaveBean(String name);
    
    // Bean retrieval for further assertions
    <T> AbstractObjectAssert<?, T> getBean(Class<T> type);
    <T> AbstractObjectAssert<?, T> getBean(Class<T> type, Scope scope);
    AbstractObjectAssert<?, Object> getBean(String name);
    <T> AbstractObjectAssert<?, T> getBean(String name, Class<T> type);
    <T> MapAssert<String, T> getBeans(Class<T> type);
    <T> MapAssert<String, T> getBeans(Class<T> type, Scope scope);
    <T> AbstractObjectArrayAssert<?, String> getBeanNames(Class<T> type);

    // Failure assertions
    ApplicationContextAssert<C> hasFailed();
    ApplicationContextAssert<C> hasNotFailed();
    AbstractThrowableAssert<?, ? extends Throwable> getFailure();
    
    enum Scope {
        NO_ANCESTORS,        // Current context only
        INCLUDE_ANCESTORS    // Include parent contexts
    }
}

Usage with Context Runners

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

@Configuration
class MyConfig {
    @Bean
    public MyService myService() {
        return new MyService();
    }
}

class ContextAssertTest {

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

    @Test
    void testBeanExists() {
        contextRunner.run(context -> {
            // Bean existence
            assertThat(context).hasBean("myService");
            assertThat(context).hasSingleBean(MyService.class);
            
            // Bean absence
            assertThat(context).doesNotHaveBean(OtherService.class);
        });
    }
    
    @Test
    void testBeanProperties() {
        contextRunner.run(context -> {
            // Get bean for assertions
            assertThat(context).getBean(MyService.class)
                .isNotNull()
                .extracting("initialized")
                .isEqualTo(true);
        });
    }
    
    @Test
    void testMultipleBeans() {
        contextRunner.run(context -> {
            // Get all beans of type
            assertThat(context).getBeans(MyPlugin.class)
                .hasSize(3)
                .containsKeys("plugin1", "plugin2", "plugin3");
        });
    }
}

Failure Assertions

@Test
void testContextFailure() {
    new ApplicationContextRunner()
        .withUserConfiguration(InvalidConfig.class)
        .run(context -> {
            assertThat(context).hasFailed();
            assertThat(context).getFailure()
                .isInstanceOf(BeanCreationException.class)
                .hasMessageContaining("required bean");
        });
}

@Test
void testContextSuccess() {
    contextRunner.run(context -> {
        assertThat(context).hasNotFailed();
    });
}

Scope-Based Lookups

@Test
void testWithParentContext() {
    ApplicationContext parent = new AnnotationConfigApplicationContext(ParentConfig.class);
    
    new ApplicationContextRunner()
        .withParent(parent)
        .withUserConfiguration(ChildConfig.class)
        .run(context -> {
            // Current context only
            assertThat(context)
                .getBeans(MyService.class, Scope.NO_ANCESTORS)
                .hasSize(1);
            
            // Include parent
            assertThat(context)
                .getBeans(MyService.class, Scope.INCLUDE_ANCESTORS)
                .hasSize(2);
        });
}

Chaining Assertions

@Test
void testChainedAssertions() {
    contextRunner.run(context -> {
        assertThat(context)
            .hasSingleBean(MyService.class)
            .hasBean("myService")
            .doesNotHaveBean(OtherService.class);

        assertThat(context).getBean(MyService.class)
            .isNotNull()
            .hasFieldOrPropertyWithValue("name", "default")
            .extracting("value")
            .isEqualTo("expected");
    });
}

Advanced Assertion Patterns

Pattern: Bean Name Assertions

@Test
void testBeanNames() {
    contextRunner
        .withUserConfiguration(MultiPluginConfig.class)
        .run(context -> {
            assertThat(context).getBeanNames(Plugin.class)
                .hasSize(3)
                .contains("plugin1", "plugin2", "plugin3")
                .allMatch(name -> name.startsWith("plugin"));
        });
}

Pattern: Multiple Beans of Same Type

@Configuration
class MultiServiceConfig {
    @Bean
    public DataProcessor primaryProcessor() {
        return new PrimaryDataProcessor();
    }

    @Bean
    public DataProcessor secondaryProcessor() {
        return new SecondaryDataProcessor();
    }

    @Bean
    public DataProcessor backupProcessor() {
        return new BackupDataProcessor();
    }
}

@Test
void testMultipleBeansOfSameType() {
    new ApplicationContextRunner()
        .withUserConfiguration(MultiServiceConfig.class)
        .run(context -> {
            assertThat(context).getBeans(DataProcessor.class)
                .hasSize(3)
                .containsKeys("primaryProcessor", "secondaryProcessor", "backupProcessor");

            assertThat(context).getBeans(DataProcessor.class)
                .extractingByKey("primaryProcessor")
                .isInstanceOf(PrimaryDataProcessor.class);
        });
}

Pattern: Bean Property Extraction

@Test
void testBeanPropertyExtraction() {
    contextRunner
        .withPropertyValues("service.name=TestService", "service.port=8080")
        .withUserConfiguration(ServiceConfig.class)
        .run(context -> {
            assertThat(context).getBean(MyService.class)
                .extracting("name", "port", "initialized")
                .containsExactly("TestService", 8080, true);
        });
}

Pattern: Nested Bean Assertions

@Test
void testNestedBeanStructure() {
    contextRunner
        .withUserConfiguration(CompositeServiceConfig.class)
        .run(context -> {
            assertThat(context).getBean(CompositeService.class)
                .isNotNull()
                .extracting("innerService")
                .isNotNull()
                .extracting("database")
                .isNotNull()
                .extracting("connectionPool")
                .satisfies(pool -> {
                    assertThat(pool).hasFieldOrPropertyWithValue("maxConnections", 10);
                });
        });
}

Pattern: Conditional Bean Presence

@Test
void testConditionalBeanCreation() {
    // When property is set
    contextRunner
        .withPropertyValues("feature.enabled=true")
        .withUserConfiguration(ConditionalConfig.class)
        .run(context -> {
            assertThat(context)
                .hasSingleBean(FeatureService.class)
                .hasBean("featureService");
        });

    // When property is not set
    contextRunner
        .withUserConfiguration(ConditionalConfig.class)
        .run(context -> {
            assertThat(context)
                .doesNotHaveBean(FeatureService.class)
                .doesNotHaveBean("featureService");
        });
}

Pattern: Bean Scope Verification

@Test
void testBeanScope() {
    contextRunner
        .withUserConfiguration(ScopedBeansConfig.class)
        .run(context -> {
            // Singleton bean
            Object bean1 = context.getBean("singletonBean");
            Object bean2 = context.getBean("singletonBean");
            assertThat(bean1).isSameAs(bean2);

            // Prototype bean
            Object proto1 = context.getBean("prototypeBean");
            Object proto2 = context.getBean("prototypeBean");
            assertThat(proto1).isNotSameAs(proto2);
        });
}

Pattern: Testing with Parent Context

@Test
void testParentContextBeans() {
    ApplicationContext parent = new AnnotationConfigApplicationContext(ParentConfig.class);

    new ApplicationContextRunner()
        .withParent(parent)
        .withUserConfiguration(ChildConfig.class)
        .run(context -> {
            // Bean from child context only
            assertThat(context)
                .hasSingleBean(ChildService.class, Scope.NO_ANCESTORS);

            // Beans from both contexts
            assertThat(context)
                .getBeans(ParentService.class, Scope.INCLUDE_ANCESTORS)
                .hasSize(1);

            assertThat(context).getBean(ChildService.class)
                .extracting("parentService")
                .isNotNull();
        });
}

Pattern: Bean Lifecycle Verification

@Test
void testBeanLifecycle() {
    contextRunner
        .withUserConfiguration(LifecycleConfig.class)
        .run(context -> {
            LifecycleBean bean = context.getBean(LifecycleBean.class);

            assertThat(bean.isInitialized()).isTrue();
            assertThat(bean.getInitCount()).isEqualTo(1);

            // Context will be closed automatically
        });
}

Pattern: Primary Bean Selection

@Configuration
class PrimaryBeanConfig {
    @Bean
    @Primary
    public DatabaseService primary() {
        return new PostgresService();
    }

    @Bean
    public DatabaseService fallback() {
        return new H2Service();
    }
}

@Test
void testPrimaryBeanSelection() {
    new ApplicationContextRunner()
        .withUserConfiguration(PrimaryBeanConfig.class)
        .run(context -> {
            assertThat(context).getBeans(DatabaseService.class)
                .hasSize(2);

            assertThat(context).getBean(DatabaseService.class)
                .isInstanceOf(PostgresService.class);
        });
}

Pattern: Bean Dependency Verification

@Test
void testBeanDependencies() {
    contextRunner
        .withUserConfiguration(DependentBeansConfig.class)
        .run(context -> {
            ServiceA serviceA = context.getBean(ServiceA.class);
            ServiceB serviceB = context.getBean(ServiceB.class);
            ServiceC serviceC = context.getBean(ServiceC.class);

            assertThat(serviceB.getServiceA()).isSameAs(serviceA);
            assertThat(serviceC.getServiceA()).isSameAs(serviceA);
            assertThat(serviceC.getServiceB()).isSameAs(serviceB);
        });
}

Pattern: Auto-Configuration Testing

@Test
void testAutoConfigurationOrder() {
    new ApplicationContextRunner()
        .withConfiguration(AutoConfigurations.of(
            DatabaseAutoConfiguration.class,
            CachingAutoConfiguration.class,
            SecurityAutoConfiguration.class
        ))
        .run(context -> {
            assertThat(context)
                .hasSingleBean(DataSource.class)
                .hasSingleBean(CacheManager.class)
                .hasSingleBean(SecurityConfig.class);

            // Verify auto-configuration ordering
            SecurityConfig security = context.getBean(SecurityConfig.class);
            assertThat(security.getDataSource()).isNotNull();
            assertThat(security.getCacheManager()).isNotNull();
        });
}

Pattern: Environment Property Verification

@Test
void testEnvironmentPropertiesAffectBeans() {
    contextRunner
        .withPropertyValues(
            "app.name=TestApp",
            "app.version=1.0.0",
            "app.debug=true"
        )
        .withUserConfiguration(AppConfig.class)
        .run(context -> {
            assertThat(context).getBean(AppInfo.class)
                .hasFieldOrPropertyWithValue("name", "TestApp")
                .hasFieldOrPropertyWithValue("version", "1.0.0")
                .hasFieldOrPropertyWithValue("debug", true);
        });
}

Pattern: Collection Bean Assertions

@Test
void testCollectionBeans() {
    contextRunner
        .withUserConfiguration(CollectionConfig.class)
        .run(context -> {
            assertThat(context).getBean("userList", List.class)
                .hasSize(3)
                .extracting("name")
                .contains("Alice", "Bob", "Charlie");

            assertThat(context).getBean("configMap", Map.class)
                .containsKeys("key1", "key2", "key3")
                .containsEntry("key1", "value1");
        });
}

Failure Testing Patterns

Pattern: Expected Startup Failures

@Test
void testExpectedStartupFailure() {
    new ApplicationContextRunner()
        .withUserConfiguration(InvalidConfig.class)
        .run(context -> {
            assertThat(context).hasFailed();

            assertThat(context).getFailure()
                .isInstanceOf(BeanCreationException.class)
                .hasMessageContaining("Could not autowire")
                .hasMessageContaining("No qualifying bean");
        });
}

Pattern: Missing Bean Failures

@Test
void testMissingDependency() {
    new ApplicationContextRunner()
        .withUserConfiguration(DependentServiceConfig.class)
        // Not providing required dependency
        .run(context -> {
            assertThat(context).hasFailed();

            assertThat(context).getFailure()
                .hasCauseInstanceOf(NoSuchBeanDefinitionException.class)
                .hasStackTraceContaining("DataSource");
        });
}

Pattern: Circular Dependency Detection

@Test
void testCircularDependencyFailure() {
    new ApplicationContextRunner()
        .withUserConfiguration(CircularConfig.class)
        .run(context -> {
            assertThat(context).hasFailed();

            assertThat(context).getFailure()
                .isInstanceOf(BeanCurrentlyInCreationException.class)
                .hasMessageContaining("circular reference")
                .hasMessageContaining("ServiceA")
                .hasMessageContaining("ServiceB");
        });
}

Pattern: Bean Validation Failures

@Test
void testBeanValidationFailure() {
    new ApplicationContextRunner()
        .withPropertyValues("service.timeout=-1") // Invalid value
        .withUserConfiguration(ValidatedServiceConfig.class)
        .run(context -> {
            assertThat(context).hasFailed();

            assertThat(context).getFailure()
                .getRootCause()
                .isInstanceOf(ConstraintViolationException.class)
                .hasMessageContaining("timeout")
                .hasMessageContaining("must be positive");
        });
}

Pattern: Configuration Property Binding Failures

@Test
void testPropertyBindingFailure() {
    new ApplicationContextRunner()
        .withPropertyValues("service.port=invalid") // Should be int
        .withUserConfiguration(ServiceConfig.class)
        .run(context -> {
            assertThat(context).hasFailed();

            assertThat(context).getFailure()
                .hasMessageContaining("Failed to bind properties")
                .hasMessageContaining("service.port");
        });
}

Pattern: Conditional Failure Verification

@Test
void testConditionalFailure() {
    // Should fail when required class is missing
    new ApplicationContextRunner()
        .withClassLoader(new FilteredClassLoader(DataSource.class))
        .withUserConfiguration(DataSourceRequiringConfig.class)
        .run(context -> {
            assertThat(context).hasFailed();

            assertThat(context).getFailure()
                .hasMessageContaining("DataSource")
                .hasCauseInstanceOf(NoClassDefFoundError.class);
        });
}

Troubleshooting

Issue: assertThat(context) doesn't have bean methods

  • Cause: Wrong assertThat import
  • Solution: Use static import from AssertJ: import static org.assertj.core.api.Assertions.assertThat;

Issue: hasSingleBean fails with multiple beans

  • Cause: Multiple beans of same type exist
  • Solution: Use getBeans() to inspect all instances

Issue: Bean assertions fail unexpectedly

  • Cause: Bean in parent context, using NO_ANCESTORS scope
  • Solution: Use INCLUDE_ANCESTORS scope or check parent

See Also

  • Context Runners - Running contexts for testing
  • Integration Testing - Full application testing