1 mockito介紹和入門(mén)官方:https://github.com/mockito/mockito 入門(mén): 5分鐘了解Mockito http://liuzhijun./blog/1512780 Mockito:一個(gè)強(qiáng)大的用于 Java 開(kāi)發(fā)的模擬測(cè)試框架 http://www.oschina.net/translate/mockito-a-great-mock-framework-for-java-development 2 spring中正常使用mockito上demo代碼: 1 @RunWith(SpringJUnit4ClassRunner.class) 2 @ContextConfiguration(locations = { "classpath:testApplicationContext.xml" }) 3 public class SpringMockitoTest { 4 5 @Mock 6 private ApiService mockApiService; 7 8 @Before 9 public void initMocks() { 10 MockitoAnnotations.initMocks(this); 11 when(mockApiService.test()).thenReturn("ok"); 12 } 13 14 @Test 15 public void should_success_when_testApiService() { 16 String result = mockApiService.test(); 17 Assert.assertEquals("ok", result); 18 } 19 } 20 21 @Component 22 public class ApiService { 23 24 @Autowired 25 private TestApiService testApiService; 26 27 public String test() { 28 String connect = testApiService.connect(); 29 connect += "test";//test自己的業(yè)務(wù) 30 return connect; 31 } 32 } 33 34 @Component 35 public class TestApiService { 36 public String connect() { 37 return "error"; 38 } 39 40 public String findFromDb() { 41 return "db_data"; 42 } 43 } 正常使用spring和mockito中,我們把需要的mock的ApiService給mock掉,,但是我們更想的是把TestApiService中的connect方法mock掉,,這樣就可以測(cè)試我們自己的代碼,也就是ApiService中test方法自己的業(yè)務(wù),。 3 spring中mock任何容器內(nèi)對(duì)象上面的demo中,我們?nèi)绾蝝ock掉TestApiService中的test方法,? 因?yàn)門(mén)estApiService是spring容器管理的bean,,并且ApiService中使用到TestApiService,所以我們把ApiService中引用的TestApiService替換成我們的mock對(duì)象即可,。 Spring框架有個(gè)反射工具ReflectionTestUtils,,可以把一個(gè)對(duì)象中屬性設(shè)置為新值,我們可以使用: ReflectionTestUtils.setField(apiService, "testApiService", spyTestApiService); 把我們mock的testApiService放到apiService中,,這樣apiService調(diào)用就是我們mock的對(duì)象了,;但是默認(rèn)spring中apiService對(duì)象是代理對(duì)象,不能直接把值設(shè)置到屬性上,,所以我們自己寫(xiě)個(gè)小的工具類,,在最后如下: ReflectionTestUtils.setField(AopTargetUtils.getTarget(apiService), "testApiService", spyTestApiService); 完整demo: 1 @RunWith(SpringJUnit4ClassRunner.class) 2 @ContextConfiguration(locations = { "classpath:testApplicationContext.xml" }) 3 public class SpringMockitoTest { 4 5 @Autowired 6 private ApiService apiService; 7 @Mock 8 private TestApiService spyTestApiService; 9 @Autowired 10 private TestApiService testApiService; 11 12 @Before 13 public void initMocks() throws Exception { 14 MockitoAnnotations.initMocks(this); 15 ReflectionTestUtils.setField(AopTargetUtils.getTarget(apiService), "testApiService", spyTestApiService); 16 when(spyTestApiService.connect()).thenReturn("ok"); 17 } 18 19 @After 20 public void clearMocks() throws Exception { 21 ReflectionTestUtils.setField(AopTargetUtils.getTarget(apiService), "testApiService", testApiService); 22 } 23 24 @Test 25 public void should_success_when_testApiService() { 26 String result = apiService.test(); 27 Assert.assertEquals("oktest", result); 28 } 29 } 30 31 @Component 32 public class ApiService { 33 34 @Autowired 35 private TestApiService testApiService; 36 37 public String test() { 38 String connect = testApiService.connect(); 39 connect += "test";//test自己的業(yè)務(wù) 40 return connect; 41 } 42 } 43 44 @Component 45 public class TestApiService { 46 public String connect() { 47 return "error"; 48 } 49 50 public String findFromDb() { 51 return "db_data"; 52 } 53 } 54 55 public class AopTargetUtils { 56 /** 57 * 獲取 目標(biāo)對(duì)象 58 * @param proxy 代理對(duì)象 59 * @return 60 * @throws Exception 61 */ 62 public static Object getTarget(Object proxy) throws Exception { 63 if(!AopUtils.isAopProxy(proxy)) { 64 return proxy;//不是代理對(duì)象 65 } 66 if(AopUtils.isJdkDynamicProxy(proxy)) { 67 return getJdkDynamicProxyTargetObject(proxy); 68 } else { //cglib 69 return getCglibProxyTargetObject(proxy); 70 } 71 } 72 73 private static Object getCglibProxyTargetObject(Object proxy) throws Exception { 74 Field h = proxy.getClass().getDeclaredField("CGLIB$CALLBACK_0"); 75 h.setAccessible(true); 76 Object dynamicAdvisedInterceptor = h.get(proxy); 77 Field advised = dynamicAdvisedInterceptor.getClass().getDeclaredField("advised"); 78 advised.setAccessible(true); 79 Object target = ((AdvisedSupport)advised.get(dynamicAdvisedInterceptor)).getTargetSource().getTarget(); 80 return target; 81 } 82 83 84 private static Object getJdkDynamicProxyTargetObject(Object proxy) throws Exception { 85 Field h = proxy.getClass().getSuperclass().getDeclaredField("h"); 86 h.setAccessible(true); 87 AopProxy aopProxy = (AopProxy) h.get(proxy); 88 Field advised = aopProxy.getClass().getDeclaredField("advised"); 89 advised.setAccessible(true); 90 Object target = ((AdvisedSupport)advised.get(aopProxy)).getTargetSource().getTarget(); 91 return target; 92 } 93 } 最后就是注意測(cè)試之后要還原現(xiàn)場(chǎng),把spring對(duì)象還原,,尤其在跑maven test的時(shí)候,,否則可能會(huì)影響其他人的測(cè)試。 |
|
來(lái)自: 埃德溫會(huì)館 > 《java》