一般咱們會把日誌,緩存等功能放到切面中實現。可是Aop的junit編寫會是一個讓人頭疼的問題,通過探索發現利用AspectJProxyFactory手工生產代理類實現aop的測試是一個不錯的主意,一來能夠省卻構建切面測試類的麻煩,二來能夠測試下切面寫的對不對。實現上並無太多高深的內容,只是筆者在實際開發中的一點小的心得和總結但願給追求clean code的你一些參考。話很少說show my code:
這是一個簡單的例子,其中Car類是返回的bean,CarCacheAop是ParkImpl切面類用的是@Around的方式來在真正調用getCar方法以前作一些緩存處理,若是緩存中可以查到則從緩存中獲取若是獲取不到則調用真實方法。具體代碼邏輯以下:spring
package com.moon.dong.demo.aop; import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.Around; import org.aspectj.lang.annotation.Aspect; @Aspect public class CarCacheAop { private CarCache cache; @Around("execution(public \* com.moon.dong.demo.aop.ParkImpl.getCar(..)) && args(id)") public Object process(ProceedingJoinPoint joinPoint, String id) throws Throwable { Car car = cache.getCar(id); if (car != null){ return car; }else { return joinPoint.proceed(joinPoint.getArgs()); } } }
測試類的邏輯以下:緩存
package com.moon.dong.demo.aop; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.Spy; import org.mockito.junit.MockitoJUnitRunner; import org.springframework.aop.aspectj.annotation.AspectJProxyFactory; import static org.junit.Assert.assertEquals; import static org.mockito.Matchers.anyString; import static org.mockito.Mockito.atLeastOnce; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; @RunWith(MockitoJUnitRunner.class) public class CarCacheAopTest { @InjectMocks private CarCacheAop aop; @Mock private CarCache cache; @Spy private ParkImpl park; private Park proxy; Car carFromCache \= new Car(); Car carFromPark \= new Car(); @Before public void setUp() throws Exception { AspectJProxyFactory factory = new AspectJProxyFactory(park); factory.addAspect(aop); proxy \= factory.getProxy(); doReturn(carFromPark).when(park).getCar(anyString()); } @Test public void process\_use\_cache() { doReturn(carFromCache).when(cache).getCar(anyString()); Car car = proxy.getCar("1111"); assertEquals(carFromCache, car); verify(cache, atLeastOnce()).getCar(anyString()); verify(park, never()).getCar(anyString()); } @Test public void process\_use\_park() { doReturn(null).when(cache).getCar(anyString()); Car car = proxy.getCar("1111"); assertEquals(carFromPark, car); verify(cache, atLeastOnce()).getCar(anyString()); verify(park, atLeastOnce()).getCar(anyString()); } }
運行結果以下:
測試
從測試中能夠發現,實現了咱們的測試預期,第一個測試中當cache中有返回則方法實際返回的是緩存中的數據而且沒有訪問實際的Park類中的getCar方法。第二個測試中當cache中返回的爲null,則訪問了Park類中的getCar方法。spa