基於spring與mockito單元測試Mock對象註入
阿新 • • 發佈:2018-08-28
err else archive ali spro 反射 lse ica sce 轉載:http://www.blogjava.net/qileilove/archive/2014/03/07/410713.html
1.關鍵詞
單元測試、spring、mockito
2.概述
單元測試目前已經成為項目中保證代碼質量的一種必要方法,對於一些不易構造或者不易獲取的對象通過mock的方式進行測試是一種很有效的處理辦法。在基於spring的mock測試中,mock對象獲取和使用的便利性可以提升單元測試代碼的質量。
3.實現原理
Mock對象的註入使用註解和反射,對象註入依賴spring框架支持junit4提供的TestExcutionListeners監聽器對象,在監聽器中將mock對象註入到單元測試類中。
4.新建對象方式代碼
5.監聽器方式代碼
5.1 實現監聽器
繼承DependencyInjectionTestExecutionListener類,
實現injectDependencies(TestContexttestContext)方法
5.2 利用反射註入mock對象
5.3 測試類配置
使用@TestExecutionListeners註解,引入監聽器,需要mock的對象加上@Mock註解。
6.總結
監聽器的方式解放了代碼中硬編碼註入mock對象,使得代碼簡潔幹凈。
private IAccessServiceaccessService = Mockito.mock(IAccessService.class); @BeforeClass public static void beforeClass(){ // 構造並註入Mock對象ICmsProxyService sceneConfigService.setAccessService(accessService); } |
public class MockitoDependencyInjectionTestExecutionListener extends DependencyInjectionTestExecutionListener { @Override protected void injectDependencies(TestContext testContext) throws Exception { super.injectDependencies(testContext); init(testContext); } |
private void init(final TestContext testContext)throws Exception { Object bean = testContext.getTestInstance(); Field[] fields = bean.getClass().getDeclaredFields(); for (Field field : fields) { Annotation[] annotations = field.getAnnotations(); for (Annotation annotation : annotations) { if(annotationinstanceof Mock){ //註入Mock實例 MockObject obj = new MockObject(); obj.setType(field.getType()); obj.setObj(Mockito.mock(field.getType())); field.setAccessible(true); field.set(bean, obj.getObj()); mockObjectMap.put(field.getName(), obj); }else if(annotation instanceofAutowired){ injectFields.add(field); } } } |
AutowireCapableBeanFactory factory =testContext.getApplicationContext().getAutowireCapableBeanFactory(); //Autowired註解註入mock對象 for (Field field :injectFields) { field.setAccessible(true); Object object = field.get(bean); if(objectinstanceof Proxy){ Class targetClass = AopUtils.getTargetClass(object); if(targetClass ==null) return; Field[] targetFields =targetClass.getDeclaredFields(); for(Field targetField : targetFields){ targetField.setAccessible(true); if(mockObjectMap.get(targetField.getName()) ==null){ continue; } targetField.set(getTargetObject(object,mockObjectMap.get(targetField.getName()).getType()),mockObjectMap.get(targetField.getName()).getObj()); } }else{ Object realObject = factory.getBean(field.getName()); if(null != realObject){ Method[] methods = realObject.getClass().getDeclaredMethods(); for (Method method : methods) { if(method.getName().equalsIgnoreCase("set" +field.getName())){ method.invoke(realObject, mockObjectMap.get(field.getName()).getObj()); } } } } } } |
@TestExecutionListeners({MockitoDependencyInjectionTestExecutionListener.class}) public class AccessServiceImplTest extends BaseTestCase{ @Autowired private IAccessServiceaccessService; @Mock private IPersonServicepersonService; @Mock private IAccessDaoaccessDao; } |
基於spring與mockito單元測試Mock對象註入