Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to add a bean in SpringBootTest

Tags:

The question seems extremely simple, but strangely enough I didn't find a solution.

My question is about adding/declaring a bean in a SpringBootTest, not overriding one, nor mocking one using mockito.

Here is what I got when trying the simplest implementation of my real need (but it doesn't work):

Some service, bean, and config:

@Value // lombok
public class MyService {
    private String name;
}

@Value // lombok
public class MyClass {
    private MyService monitoring;
}

@Configuration
public class SomeSpringConfig {

    @Bean
    public MyClass makeMyClass(MyService monitoring){
        return new MyClass(monitoring);
    }
}

The test:

@RunWith(SpringRunner.class)
@SpringBootTest(classes = { SomeSpringConfig.class })
public class SomeSpringConfigTest {

    private String testValue = "testServiceName";

    // this bean is not used
    @Bean
    public MyService monitoringService(){ return new MyService(testValue); }

    // thus this bean cannot be constructed using SomeSpringConfig 
    @Autowired
    public MyClass myClass;

    @Test
    public void theTest(){
        assert(myClass.getMonitoring().getName() == testValue);
    }
}

Now, if I replace the @Bean public MyService monitoring(){ ... } by @MockBean public MyService monitoring;, it works. I find it strange that I can easily mock a bean, but not simply provide it.

=> So how should I add a bean of my own for one test?

Edit:

  • I think ThreeDots's answer (create a config test class) is the general recommendation.
  • However, Danylo's answer (use @ContextConfiguration) fit better to what I asked, i.e. add @Bean directly in the test class.
like image 589
Juh_ Avatar asked Sep 03 '19 13:09

Juh_


2 Answers

Spring Test needs to know what configuration you are using (and hence where to scan for beans that it loads). To achieve what you want you have more options, the most basic ones are these two:

  1. Create configuration class outside the test class that includes your bean

    @Configuration
    public class TestConfig {
    
        @Bean
        public MyService monitoringService() {
            return new MyService();
        }
    }
    

and then add it to to test as configuration class @SpringBootTest(classes = { SomeSpringConfig.class, TestConfig.class })

or

  1. If you only need to use this configuration in this particular test, you can define it in static inner class

    public class SomeSpringConfigTest {
    
        @Configuration
        static class ContextConfiguration {
    
            @Bean
            public MyService monitoringService() {
                return new MyService();
            }
        }
    }
    

this will be automatically recognized and loaded by spring boot test

like image 78
ThreeDots Avatar answered Nov 15 '22 04:11

ThreeDots


Simply add the config as

@ContextHierarchy({
    @ContextConfiguration(classes = SomeSpringConfig.class)
})
like image 20
Danylo Rosiichuk Avatar answered Nov 15 '22 04:11

Danylo Rosiichuk