轉載: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等方法來模擬輸入,去測試相關的代碼片斷。