Generic Top

I just announced the new Learn Spring course, focused on the fundamentals of Spring 5 and Spring Boot 2:

>> CHECK OUT THE COURSE

If you have a few years of experience in the Java ecosystem, and you're interested in sharing that experience with the community (and getting paid for your work of course), have a look at the "Write for Us" page. Cheers. Eugen

1. Overview

In this quick tutorial, we’ll discuss how to exclude auto-configuration classes from Spring Boot tests.

Spring Boot’s auto-configuration feature is very handy, as it takes care of a lot of setup for us. However, this can also be an issue during testing if we don’t want a certain auto-configuration to interfere with our tests of a module.

A common example of this is the security auto-configuration, which we’ll also use for our examples.

2. Test Example

First, we’ll take a look at our testing example.

We’ll have a secured Spring Boot application with a simple home page.

When we try to access the home page without authentication, the response is “401 UNAUTHORIZED”.

Let’s see this in a test that uses REST-assured to make the call:

@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class, webEnvironment = WebEnvironment.DEFINED_PORT)
public class AutoConfigIntegrationTest {

    @Test
    public void givenNoAuthentication_whenAccessHome_thenUnauthorized() {
        int statusCode = RestAssured.get("http://localhost:8080/").statusCode();
        
        assertEquals(HttpStatus.UNAUTHORIZED.value(), statusCode);
    }
    
}

On the other hand, we can access the home page successfully with authentication:

@Test
public void givenAuthentication_whenAccessHome_thenOK() {
    int statusCode = RestAssured.given().auth().basic("john", "123")
      .get("http://localhost:8080/")
      .statusCode();
    
    assertEquals(HttpStatus.OK.value(), statusCode);
}

In the following sections, we’ll try different ways to exclude the SecurityAutoConfiguration class from our tests’ configuration.

3. Using @EnableAutoConfiguration

There are multiple ways to exclude a specific Auto-configuration class from tests’ configuration.

First, let’s see how we can use the @EnableAutoConfiguration(exclude={CLASS_NAME}) annotation:

@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class, webEnvironment = WebEnvironment.DEFINED_PORT)
@EnableAutoConfiguration(exclude=SecurityAutoConfiguration.class)
public class ExcludeAutoConfigIntegrationTest {

    @Test
    public void givenSecurityConfigExcluded_whenAccessHome_thenNoAuthenticationRequired() {
        int statusCode = RestAssured.get("http://localhost:8080/").statusCode();
        
        assertEquals(HttpStatus.OK.value(), statusCode);
    }
}

In this example, we excluded the SecurityAutoConfiguration class using the exclude attribute, but we can do the same with any of the auto-configuration classes.

Now we can run our test that accesses the home page without authentication and it will no longer fail.

4. Using @TestPropertySource

Next, we can use @TestPropertySource to inject the property “spring.autoconfigure.exclude:

@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class, webEnvironment = WebEnvironment.DEFINED_PORT)
@TestPropertySource(properties = 
 "spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration")
public class ExcludeAutoConfigIntegrationTest {
    // ...
}

Note that we need to specify the full class name (package name+simple name) for the property.

5. Using Profiles

We can also set the property “spring.autoconfigure.exclude” for our tests using profiles:

@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class, webEnvironment = WebEnvironment.DEFINED_PORT)
@ActiveProfiles("test")
public class ExcludeAutoConfigIntegrationTest {
    // ...
}

And include all “test” profile specific properties in application-test.properties:

spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration

6. Using a Custom Test Configuration

Finally, we can use a separate configuration application for our tests:

@RunWith(SpringRunner.class)
@SpringBootTest(classes = TestApplication.class, webEnvironment = WebEnvironment.DEFINED_PORT)
public class ExcludeAutoConfigIntegrationTest {
    // ...
}

And exclude the auto-configuration class from @SpringBootApplication(exclude={CLASS_NAME}):

@SpringBootApplication(exclude=SecurityAutoConfiguration.class)
public class TestApplication {

    public static void main(String[] args) {
        SpringApplication.run(TestApplication.class, args);
    }
}

7. Conclusion

In this article, we explored different ways to exclude auto-configuration classes from Spring Boot tests.

The full source code is available over on GitHub.

Generic bottom

I just announced the new Learn Spring course, focused on the fundamentals of Spring 5 and Spring Boot 2:

>> CHECK OUT THE COURSE