Java
Spring Boot
Testing
Test Context
Configuration Exclusion

Java Spring Boot Test How to exclude java configuration class from test context

Data Structures & Algorithms practice on Codemia

Step through 300+ coding interview problems with animated visualisers that show the data structure changing as the code runs. The Blind 75 are free.

Practice algorithms

Introduction

When running Spring Boot tests, you often need to exclude certain configuration classes that interfere with testing — database configs, external service clients, or security configurations. Spring Boot provides several ways to do this: @SpringBootTest(exclude=...) for auto-configuration, @TestConfiguration for overrides, @Import for selective loading, and @MockBean for replacing individual beans. The right approach depends on whether you are excluding an auto-configuration class or a custom @Configuration class.

Excluding Auto-Configuration Classes

For Spring Boot auto-configuration classes (like DataSourceAutoConfiguration):

java
1@SpringBootTest
2@EnableAutoConfiguration(exclude = {
3    DataSourceAutoConfiguration.class,
4    SecurityAutoConfiguration.class
5})
6class MyServiceTest {
7    @Test
8    void testSomething() {
9        // No database or security context loaded
10    }
11}

Or in application-test.properties:

properties
spring.autoconfigure.exclude=\
  org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration,\
  org.springframework.boot.autoconfigure.security.servlet.SecurityAutoConfiguration

Excluding Custom @Configuration Classes

For your own @Configuration classes, the approach is different because exclude only works with auto-configuration:

Method 1: Use @Profile

java
1// Production configuration
2@Configuration
3@Profile("!test")
4public class ExternalServiceConfig {
5    @Bean
6    public ExternalClient externalClient() {
7        return new ExternalClient("https://api.example.com");
8    }
9}
10
11// Test — activate "test" profile
12@SpringBootTest
13@ActiveProfiles("test")
14class MyServiceTest {
15    // ExternalServiceConfig is not loaded because profile is "test"
16}

The @Profile("!test") annotation means "load this configuration in every profile except test."

Method 2: @TestConfiguration Override

java
1// Production config
2@Configuration
3public class CacheConfig {
4    @Bean
5    public CacheManager cacheManager() {
6        return new RedisCacheManager(redisConnectionFactory());
7    }
8}
9
10// Test override — replaces the production bean
11@TestConfiguration
12public class TestCacheConfig {
13    @Bean
14    public CacheManager cacheManager() {
15        return new ConcurrentMapCacheManager();  // In-memory for tests
16    }
17}
18
19@SpringBootTest
20@Import(TestCacheConfig.class)
21class MyServiceTest {
22    @Autowired
23    private CacheManager cacheManager;  // Gets the test version
24}

@TestConfiguration beans override production beans with the same name and type.

Method 3: @ComponentScan.Filter

java
1@SpringBootTest
2@ComponentScan(excludeFilters = @ComponentScan.Filter(
3    type = FilterType.ASSIGNABLE_TYPE,
4    classes = {ExternalServiceConfig.class, BatchJobConfig.class}
5))
6class MyServiceTest {
7    // These configs are excluded from scanning
8}

Method 4: Selective @Import

Instead of loading the full application context, import only what you need:

java
1@ExtendWith(SpringExtension.class)
2@Import({MyService.class, MyRepository.class, TestDatabaseConfig.class})
3class MyServiceTest {
4    @Autowired
5    private MyService myService;
6
7    // Only the imported beans are available — no other configs loaded
8}

Using @MockBean to Replace Beans

Instead of excluding entire configurations, mock individual beans:

java
1@SpringBootTest
2class OrderServiceTest {
3
4    @MockBean
5    private PaymentGateway paymentGateway;  // Replaces real bean with mock
6
7    @MockBean
8    private EmailService emailService;
9
10    @Autowired
11    private OrderService orderService;
12
13    @Test
14    void testPlaceOrder() {
15        when(paymentGateway.charge(any())).thenReturn(true);
16
17        orderService.placeOrder(new Order());
18
19        verify(paymentGateway).charge(any());
20        verify(emailService).sendConfirmation(any());
21    }
22}

@MockBean adds a Mockito mock to the Spring context, replacing any existing bean of that type.

@WebMvcTest with Controller Isolation

java
1// Only loads web layer — no services, repos, or custom configs
2@WebMvcTest(UserController.class)
3class UserControllerTest {
4
5    @Autowired
6    private MockMvc mockMvc;
7
8    @MockBean
9    private UserService userService;  // Mock the dependency
10
11    @Test
12    void testGetUser() throws Exception {
13        when(userService.findById(1L)).thenReturn(new User("Alice"));
14
15        mockMvc.perform(get("/users/1"))
16            .andExpect(status().isOk())
17            .andExpect(jsonPath("$.name").value("Alice"));
18    }
19}

@WebMvcTest only loads the specified controller and web-related beans. All service and repository beans must be mocked.

@DataJpaTest for Repository Isolation

java
1@DataJpaTest
2class UserRepositoryTest {
3    // Only loads JPA-related beans
4    // Uses embedded H2 by default
5    // Custom configs (security, messaging, etc.) are NOT loaded
6
7    @Autowired
8    private UserRepository userRepository;
9
10    @Test
11    void testFindByEmail() {
12        userRepository.save(new User("[email protected]", "Alice"));
13
14        User found = userRepository.findByEmail("[email protected]");
15        assertEquals("Alice", found.getName());
16    }
17}

Conditional Configuration Loading

java
1@Configuration
2@ConditionalOnProperty(name = "feature.messaging.enabled", havingValue = "true")
3public class MessagingConfig {
4    @Bean
5    public MessageBroker messageBroker() {
6        return new RabbitMQBroker();
7    }
8}
9
10// In test properties: feature.messaging.enabled=false
11// MessagingConfig is not loaded

Common Pitfalls

  • Using exclude for custom @Configuration classes: The exclude parameter on @SpringBootTest and @EnableAutoConfiguration only works for auto-configuration classes (those listed in META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports). For custom configs, use @Profile, @TestConfiguration, or @ComponentScan.Filter.
  • @TestConfiguration not being picked up: @TestConfiguration classes in separate files are not automatically scanned. You must add @Import(TestConfig.class) to your test or place the inner @TestConfiguration class inside the test class.
  • @MockBean replacing the wrong bean: If you have multiple beans of the same type, @MockBean replaces all of them. Use @Qualifier to target a specific bean.
  • Context caching issues: Spring caches test application contexts. Changing which configs are excluded creates a new context, slowing down the test suite. Group tests with the same context configuration.
  • @ActiveProfiles("test") not working: Ensure @Profile("!test") is on the config class, not on individual @Bean methods (unless you want fine-grained control). Profile annotations on @Configuration affect all beans in that class.

Summary

  • Use @EnableAutoConfiguration(exclude = ...) for Spring Boot auto-configuration classes
  • Use @Profile("!test") + @ActiveProfiles("test") for custom @Configuration classes
  • Use @TestConfiguration with @Import to override production beans in tests
  • Use @MockBean to replace individual beans with Mockito mocks
  • Use slice tests (@WebMvcTest, @DataJpaTest) to load only relevant beans
  • Prefer narrow test contexts over full @SpringBootTest when you only need a few beans

Course
Intermediate
27 lessons
14 hours
OOD Fundamentals

Master object-oriented design from first principles, SOLID, design patterns, and classic interview problems with hands-on coding.

View the course
Data Structures & Algorithms practice on Codemia

Step through 300+ coding interview problems with animated visualisers that show the data structure changing as the code runs. The Blind 75 are free.

Practice algorithms