Testing auto-configurations with Spring Boot 2.0

Engineering | Madhura Bhave | March 07, 2018 | ...

Auto-configuration is one of the most powerful features of Spring Boot. Tests for auto-configuration classes usually follow the same pattern. Most tests start up an ApplicationContext with the auto-configuration class under test and depending on the test, also load additional configuration to simulate user behavior. The recurrence of this pattern can add a lot of repetition in the code base.

Spring Boot 2.0 provides a suite of new test helpers for easily configuring an ApplicationContext to simulate auto-configuration test scenarios. The following example configures an ApplicationContextRunner to test the UserServiceAutoConfiguration:

private final ApplicationContextRunner contextRunner = new ApplicationContextRunner()
    .withConfiguration(AutoConfigurations.of(UserServiceAutoConfiguration.class));

Since most tests in a test class share similar configuration, ApplicationContextRunner is best used as a field of the test class that is set up with some common configuration.

Each test can further customize the ApplicationContext with the desired configuration and properties.

@Test
public void someTest() {
    this.contextRunner
        .withPropertyValues("user.my.property=test")
	    .withUserConfiguration(MyConfiguration.class)
	    .run(...);
}

In addition to invoking UserServiceAutoConfiguration, the example above registers MyConfiguration and sets the user.my.property property to test.

ApplicationContextRunner transparently replicates the configuration initialization order that Spring Boot uses (scanning user configuration first, then auto-configurations according to their defined order).

There is support for an AssertableApplicationContext which provides AssertJ style assertions on an ApplicationContext. You can also chain multiple assertions as shown in the following example:

@Test
public void someTest() {
    this.contextRunner.run((context) -> {
        assertThat(context).hasSingleBean(MyBean.class);
        assertThat(context).getBeanNames(UserRule.class).hasSize(2);
    });
}

Assertions can also be used on an ApplicationContext that has failed to start to check the cause of the failure. Regardless, the lifecycle of the context does not need to be managed by the test anymore, i.e the context is automatically closed.

For tests that require a WebApplicationContext, WebApplicationContextRunner or ReactiveWebApplicationContextRunner can be used.

An auto-configuration can also be affected by the presence of a particular Class on the classpath using the @ConditionalOnClass annotation. ApplicationContextRunner lets you test what happens when a given Class is not present at runtime. Spring Boot ships with a FilteredClassLoader that can easily be used by the runner. In the following example, we assert that if UserService is not present, the auto-configuration is properly disabled:

@Test
public void serviceIsIgnoredIfLibraryIsNotPresent() {
    this.contextRunner
        .withClassLoader(new FilteredClassLoader(UserService.class))
        .run((context) -> assertThat(context)
                .doesNotHaveBean("userService"));
}

Get the Spring newsletter

Stay connected with the Spring newsletter

Subscribe

Get ahead

VMware offers training and certification to turbo-charge your progress.

Learn more

Get support

Tanzu Spring offers support and binaries for OpenJDK™, Spring, and Apache Tomcat® in one simple subscription.

Learn more

Upcoming events

Check out all the upcoming events in the Spring community.

View all