Injecting Mockito mocks into a Spring bean

后端 未结 22 1486
庸人自扰
庸人自扰 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:15

    I use a combination of the approach used in answer by Markus T and a simple helper implementation of ImportBeanDefinitionRegistrar that looks for a custom annotation (@MockedBeans) in which one can specify which classes are to be mocked. I believe that this approach results in a concise unit test with some of the boilerplate code related to mocking removed.

    Here's how a sample unit test looks with that approach:

    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(loader=AnnotationConfigContextLoader.class)
    public class ExampleServiceIntegrationTest {
    
        //our service under test, with mocked dependencies injected
        @Autowired
        ExampleService exampleService;
    
        //we can autowire mocked beans if we need to used them in tests
        @Autowired
        DependencyBeanA dependencyBeanA;
    
        @Test
        public void testSomeMethod() {
            ...
            exampleService.someMethod();
            ...
            verify(dependencyBeanA, times(1)).someDependencyMethod();
        }
    
        /**
         * Inner class configuration object for this test. Spring will read it thanks to
         * @ContextConfiguration(loader=AnnotationConfigContextLoader.class) annotation on the test class.
         */
        @Configuration
        @Import(TestAppConfig.class) //TestAppConfig may contain some common integration testing configuration
        @MockedBeans({DependencyBeanA.class, DependencyBeanB.class, AnotherDependency.class}) //Beans to be mocked
        static class ContextConfiguration {
    
            @Bean
            public ExampleService exampleService() {
                return new ExampleService(); //our service under test
            }
        }
    }
    

    To make this happen you need to define two simple helper classes - custom annotation (@MockedBeans) and a custom ImportBeanDefinitionRegistrar implementation. @MockedBeans annotation definition needs to be annotated with @Import(CustomImportBeanDefinitionRegistrar.class) and the ImportBeanDefinitionRgistrar needs to add mocked beans definitions to the configuration in it's registerBeanDefinitions method.

    If you like the approach you can find sample implementations on my blogpost.

提交回复
热议问题