Injecting Mockito mocks into a Spring bean

后端 未结 22 1620
庸人自扰
庸人自扰 2020-11-22 09:44

I would like to inject a Mockito mock object into a Spring (3+) bean for the purposes of unit testing with JUnit. My bean dependencies are currently injected by using the

22条回答
  •  梦谈多话
    2020-11-22 10:10

    If you're using Spring Boot 1.4, it has an awesome way of doing this. Just use new brand @SpringBootTest on your class and @MockBean on the field and Spring Boot will create a mock of this type and it will inject it into the context (instead of injecting the original one):

    @RunWith(SpringRunner.class)
    @SpringBootTest
    public class MyTests {
    
        @MockBean
        private RemoteService remoteService;
    
        @Autowired
        private Reverser reverser;
    
        @Test
        public void exampleTest() {
            // RemoteService has been injected into the reverser bean
            given(this.remoteService.someCall()).willReturn("mock");
            String reverse = reverser.reverseSomeCall();
            assertThat(reverse).isEqualTo("kcom");
        }
    
    }
    

    On the other hand, if you're not using Spring Boot or are you using a previous version, you'll have to do a bit more work:

    Create a @Configuration bean that injects your mocks into Spring context:

    @Configuration
    @Profile("useMocks")
    public class MockConfigurer {
    
        @Bean
        @Primary
        public MyBean myBeanSpy() {
            return mock(MyBean.class);
        }
    }
    

    Using @Primary annotation you're telling spring that this bean has priority if no qualifier are specified.

    Make sure you annotate the class with @Profile("useMocks") in order to control which classes will use the mock and which ones will use the real bean.

    Finally, in your test, activate userMocks profile:

    @RunWith(SpringJUnit4ClassRunner.class)
    @SpringApplicationConfiguration(classes = {Application.class})
    @WebIntegrationTest
    @ActiveProfiles(profiles={"useMocks"})
    public class YourIntegrationTestIT {
    
        @Inject
        private MyBean myBean; //It will be the mock!
    
    
        @Test
        public void test() {
            ....
        }
    }
    

    If you don't want to use the mock but the real bean, just don't activate useMocks profile:

    @RunWith(SpringJUnit4ClassRunner.class)
    @SpringApplicationConfiguration(classes = {Application.class})
    @WebIntegrationTest
    public class AnotherIntegrationTestIT {
    
        @Inject
        private MyBean myBean; //It will be the real implementation!
    
    
        @Test
        public void test() {
            ....
        }
    }
    

提交回复
热议问题