Overriding an Autowired Bean in Unit Tests

前端 未结 5 718
爱一瞬间的悲伤
爱一瞬间的悲伤 2020-12-04 19:09

Is there a simple way I can easily override an autowired bean in specific unit tests? There is only a single bean of every type in the compile classes so it\'s not a problem

相关标签:
5条回答
  • 2020-12-04 19:18

    If you just simply want to provide a different bean in your tests, i think you don't need to use spring profiles or mockito.

    Just do the following:

    @RunWith(SpringJUnit4ClassRunner.class)
    @SpringApplicationConfiguration(classes = { TestConfig.class })
    public class MyTest
    {
        @Configuration
        @Import(Application.class) // the actual configuration
        public static class TestConfig
        {
            @Bean
            public IMyService myService()
            {
                return new MockedMyService();
            }
        }
    
        @Test
        public void test()
        {
            ....
        }
    }
    

    NOTE: tested with spring boot 1.3.2 / spring 4.2.4

    0 讨论(0)
  • 2020-12-04 19:23

    As mats.nowak commented, @ContextConfiguration is useful for this.

    Say a parent test class is like:

    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(locations = {"classpath:spring/some-dao-stuff.xml"
        ,"classpath:spring/some-rest-stuff.xml"
        ,"classpath:spring/some-common-stuff.xml"
        ,"classpath:spring/some-aop-stuff.xml"
        ,"classpath:spring/some-logging-stuff.xml"
        ,"classpath:spring/some-services-etc.xml"
    })
    public class MyCompaniesBigTestSpringConfig {
    ...
    

    Create a child test class:

    package x.y.z;
    @ContextConfiguration
    public class MyOneOffTest extends MyCompaniesBigTestSpringConfig {
    ...
    

    and put in src/test/resources/x/y/z/MyOneOffTest-context.xml

    <beans xmlns="http://www.springframework.org/schema/beans"
           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
           xmlns:context="http://www.springframework.org/schema/context"
           xsi:schemaLocation="http://www.springframework.org/schema/beans
                               http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
                               http://www.springframework.org/schema/context
                               http://www.springframework.org/schema/context/spring-context-3.0.xsd">
    
    
        <bean id="widgetsService" class="com.mycompany.mydept.myservice.WidgetsService" primary="true" />
    
    </beans>
    

    That widgetsService bean will override (take the place of) the bean defined in the main config xml (or Java config). See about inheritLocations Also Note the default -context.xml file. Example of that here. Update: I had to add primary="true", apparently it's needed.

    0 讨论(0)
  • 2020-12-04 19:25

    You should use spring profiles in order to know what kind of bean you want to use in different contexts.

    http://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-profiles.html

    0 讨论(0)
  • 2020-12-04 19:26

    I had similar problem and I solved with a mix and I find this one more useful and reusable. I created a spring profile for the tests and a config class that overrides the beans I want to mock in a very simple way:

    @Profile("test")
    @Configuration
    @Import(ApplicationConfiguration.class)
    public class ConfigurationTests {
    
        @MockBean
        private Producer kafkaProducer;
    
        @MockBean
        private SlackNotifier slackNotifier;
    
    }
    

    By doing that I can @Autowire those mock beans and use mockito to verify on them. Main advantage is that now all tests seamlessly get the mock beans without any per-test change. Tested with:

    spring boot 1.4.2

    0 讨论(0)
  • 2020-12-04 19:31

    In Spring Boot 1.4 there's a simple way for doing that:

    @RunWith(SpringRunner.class)
    @SpringBootTest(classes = { MyApplication.class })
    public class MyTests {
        @MockBean
        private MyBeanClass myTestBean;
    
        @Before
        public void setup() {
             ...
             when(myTestBean.doSomething()).thenReturn(someResult);
        }
    
        @Test
        public void test() {
             // MyBeanClass bean is replaced with myTestBean in the ApplicationContext here
        }
    }
    
    0 讨论(0)
提交回复
热议问题