当对一个切面类进行测试时,因为Spring对切面对象生成了proxy对象,此时对切面对象使用ReflectionTestUtils赋值,操做的是proxy对象,而不是真实对象,会使得赋值出问题。能够经过引入AopTestUtils解决赋值问题。html
经过AopTestUtils能够经过切面proxy对象,获取到切面的真实对象。经过使用ReflectionTestUtils对真实的切面对象修改依赖,到达mock的目的。java
准备切面对象:
IBar:git
package com.github.yongzhizhan.draftbox.springtest.aop; public interface IBar { String perform(String message); }
Bar:github
package com.github.yongzhizhan.draftbox.springtest.aop; import org.springframework.beans.factory.annotation.Autowired; public class Bar implements IBar { @Autowired Dep dep; @Override public String perform(final String message) { System.out.println("run bar " + message); return dep.perform("aspect"); } }
依赖对象:web
package com.github.yongzhizhan.draftbox.springtest.aop; /** * Dependence class * @author zhanyongzhi */ public class Dep { public String perform(String msg){ return msg; } }
切面:spring
package com.github.yongzhizhan.draftbox.springtest.aop; import org.aspectj.lang.JoinPoint; import org.aspectj.lang.annotation.Aspect; import org.aspectj.lang.annotation.Before; /** * 切面 */ @Aspect public class BarAspect { @Before(value = "execution(* com.github.yongzhizhan.draftbox.springtest.aop.Bar.perform(..))") public void beforeSayHello(JoinPoint vJoinPoint){ System.out.println("aspect before "+vJoinPoint.getArgs()[0]); } }
package com.github.yongzhizhan.draftbox.springtest; import com.github.yongzhizhan.draftbox.springtest.aop.Bar; import com.github.yongzhizhan.draftbox.springtest.aop.BarAspect; import com.github.yongzhizhan.draftbox.springtest.aop.Dep; import com.github.yongzhizhan.draftbox.springtest.aop.IBar; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.util.AopTestUtils; import org.springframework.test.util.ReflectionTestUtils; import static org.mockito.Mockito.when; /** * 经过AopTestUtils解决ReflectionTestUtils赋值切面对象的问题 * @author zhanyongzhi */ @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration("classpath*:**web-config.xml") public class AopTestUtilsTest { @Mock Dep dep; @Autowired private BarAspect barAspect; @Autowired ApplicationContext applicationContext; @Autowired @InjectMocks IBar bar; @Before public void setUp(){ MockitoAnnotations.initMocks(this); //对象默认返回aspect,修改成返回mock when(dep.perform("aspect")).thenReturn("mock"); } @Test public void testDefault(){ String tRet = bar.perform("hello"); //mock注入无效,仍然返回aspect if(!"aspect".equals(tRet)) Assert.fail("perform return not equeal aspect"); } @Test public void testAopUtils(){ //获取真实的代理对象 Bar tBar = AopTestUtils.getTargetObject(bar); ReflectionTestUtils.setField(tBar, "dep", dep); String tRet = bar.perform("hello"); //此时才真正mock到 if(!"mock".equals(tRet)) Assert.fail("perform return not equeal mock"); } }
配置文件:spring-mvc
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.1.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-4.1.xsd"> <!-- scan the package and the sub package --> <mvc:annotation-driven/> <context:component-scan base-package="com.github.yongzhizhan.draftbox.springtest"/> <bean id="bar" class="com.github.yongzhizhan.draftbox.springtest.aop.Bar"/> <bean id="dep" class="com.github.yongzhizhan.draftbox.springtest.aop.Dep"/> <bean id="barAspect" class="com.github.yongzhizhan.draftbox.springtest.aop.BarAspect"/> <aop:aspectj-autoproxy/> </beans>
在github中查看mvc
spring-aop-aspect-not-working-using-mockito
mockito-and-spring-proxies
is-it-possible-to-unproxy-a-spring-beanapp