Excluding Configuration in Spring boot test

10,451

First, I don't like the idea of putting a config class in another class. I don't know if that is frenquently made, I'm kinda new to Spring. But here is what I would do :

First config file :

@Configuration
@Import(MyConfiguration.class)
public class MyTestConfiguration {
    @Bean
    @Primary // added to let know on @Autowired to use this one instead of the one in first MyConfiguration.class
    public A beanA() {
      return mock(A.class);
    }    
}

Second config file :

@Configuration
@Import(MyConfiguration.class)
public class MyOtherTestConfiguration {
    @Bean
    public B beanB() {
      return new B()
    }    
}

I'm not familiar with @TestConfiguration. That's why i'm using @Configuration.

First test class :

package com.example;
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = MyTestConfiguration.class)
public class SpringConfigurationTest {

}

Second test class :

package com.example.sub;
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = MyOtherTestConfiguration.class)
public class AnotherSpringConfigurationTest {

}
Share:
10,451
hotzst
Author by

hotzst

Professionally I am working for the Swiss based company Netcetera mainly in a capacity of technical advisor with the occasional opportunity to produce some code myself. To be able to do that one has to keep abreast with the technical developments. For that reason, among others, I am programming the game OpenPatrician, which is a Java based reimplementation of "The Patrician III" using JavaFX for the UI and Spring in the background.

Updated on June 23, 2022

Comments

  • hotzst
    hotzst almost 2 years

    I have the following setup in a maven project. Configuration class for the productive code:

    package com.example;
    @Configuration
    public class MyConfiguration {
        @Bean
        public A beanA() {
          return new A();
        }
        ...
    }
    

    Then I have one test, that has an internal Configuration:

    package com.example;
    @RunWith(SpringRunner.class)
    @ContextConfiguration(classes = {MyConfiguration.class, SpringConfigurationTest.MyTestConfiguration.class})
    public class SpringConfigurationTest {
        @TestConfiguration
        static class MyTestConfiguration {
            @Bean
            @Primary
            public A beanA() {
              return mock(A.class);
            }    
        }
    }
    

    The tests in this class work fine. Then I do have another Test class in sub package:

    package com.example.sub;
    @RunWith(SpringRunner.class)
    @ContextConfiguration(classes = {MyConfiguration.class, AnotherSpringConfigurationTest.MyTestConfiguration.class})
    public class AnotherSpringConfigurationTest {
        @TestConfiguration
        static class MyTestConfiguration {
            @Bean
            public B beanB() {
              return new B()
            }    
        }
    }
    

    When running tests in this class the test configuration from SpringConfigurationTest.MyTestConfiguration is also included. My guess the reason for this is the inclusion of MyConfiguration which lies in the root directory. The effect is that in AnotherSpringConfigurationTest the bean A is mocked instead of a real instance.

    How can I avoid that configuration classes inside other tests are 'leaked' into other tests?

    I have seen Spring-boot default profile for integration tests which uses Spring profiles in Spring Boot 1.4.1, while I am using Spring Boot 2.0.1. Though I am sure it could be done.

    Another approach I could think of would be to use component scanning to pick up the contexts and exclude all those that I do not want, but that is a bit cumbersome, as I would much prefer an approach where I define what I want to use instead of what should not be used.

    Is there an easy and elegant solution with Spring Boot 2 to avoid conflicting context configurations?

  • hotzst
    hotzst almost 6 years
    I had the configurations in a separate file, but that did not change a thing.
  • GabLeg
    GabLeg almost 6 years
    It's not that it will not work, I just don't like the concept.
  • hotzst
    hotzst almost 6 years
    Tried your approach with having one configuration and bringing in the others with @Import. Did not work, I assume because Spring boot just does not work that way, but takes the configuration as root to scan for further beans, which configurations are one kind of.
  • GabLeg
    GabLeg almost 6 years
    I tried the setup you provided and it worked with no problem. So I don't think the problem is on your test setup.