當對一個切面類進行測試時,因爲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