轉載:https://blog.csdn.net/m0_38043362/article/details/80111957
1. 原理介紹
通過BeanFactoryPostProcessor向BeanFactory中注冊需要進行Mock的對象,使當前Bean容器在依賴注入時使用
我們提供的Mock對象注入到實例中使用。
具體需要交給容器管理的mock實例,是通過TestExecutionListener在容器開始啟動前去解析當前測試類中的使用@Mock
注解的字段,然后根據類型創建對應的Mock實例,將創建出來的Mock實例通過BeanFactoryPostProcessor注冊到容器中,
以供依賴注入使用。
2.代碼實現
注冊Mock實例部分
public class MockitoBeansPostProcessor implements BeanFactoryPostProcessor { @Override public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException { Map<Class<?>, MockitoBeansTestExecutionListener.MockBeanWrapper> allMockBeans = MockitoBeansTestExecutionListener.resolvedAllMockBeans(); for (Map.Entry<Class<?>, MockitoBeansTestExecutionListener.MockBeanWrapper> mockBeanWrapperEntry : allMockBeans.entrySet()) { beanFactory.registerResolvableDependency(mockBeanWrapperEntry.getKey(), mockBeanWrapperEntry.getValue().getMockObject()); } } }
解析@Mock注解部分
public class MockitoBeansTestExecutionListener extends AbstractTestExecutionListener { private static final Map<Class<?>, MockBeanWrapper> mockBeans = new ConcurrentHashMap<>(30); private static final Map<Class<?>, List<Field>> injectMockBeans = new ConcurrentHashMap<>(30); private static boolean hasInitialized = false; public static Map<Class<?>, MockBeanWrapper> resolvedAllMockBeans() { Assert.isTrue(hasInitialized); return Collections.unmodifiableMap(mockBeans); } @Override public void beforeTestClass(TestContext testContext) throws Exception { Field[] declaredFields = testContext.getTestClass().getDeclaredFields();
3.使用Demo
MessageSupplier是將要進行Mock的接口
public interface MessageSupplier { String getMessage(); }
這個是依賴MessageSupplier的實例類
@Service public class SomeService { @Autowired MessageSupplier messageSupplier; public void printMessage() { System.out.println(messageSupplier.getMessage()); } }
單元測試類
@TestExecutionListeners({MockitoBeansTestExecutionListener.class}) @ContextConfiguration(classes = {SimpleTestCase.class}) @ComponentScan(basePackageClasses = {SimpleTestCase.class}) public class SimpleTestCase extends AbstractJUnit4SpringContextTests { @Autowired private SomeService someService; @Mock MessageSupplier messageSupplier; @Test public void test() { doReturn("this is mock message.") .when(messageSupplier) .getMessage(); someService.printMessage();
4.總結
在使用微服務的系統架構中,做一次單元測試會比較麻煩,可能需要啟N多關聯服務或者去連接N多關聯服務。
這就使得單元測試很難實行,在這種情況下可以通過上面的方法將在本模塊中不存在的實例都通過Mock實例
使用,這樣使用Mockito中的doReturn等方法來模擬輸入,去測試相關的代碼片段。