通常我们会把日志,缓存等功能放到切面中实现。但是Aop的junit编写会是一个让人头疼的问题,经过探索发现利用AspectJProxyFactory手工生产代理类实现aop的测试是一个不错的主意,一来可以省却构建切面测试类的麻烦,二来可以测试下切面写的对不对。实现上并没有太多高深的内容,只是笔者在实际开发中的一点小的心得和总结希望给追求clean code的你一些参考。话不多说show my code:
这是一个简单的例子,其中Car类是返回的bean,CarCacheAop是ParkImpl切面类用的是@Around的方式来在真正调用getCar方法之前做一些缓存处理,如果缓存中能够查到则从缓存中获取如果获取不到则调用真实方法。具体代码逻辑如下:
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方法。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。