2014-02-12 192 views
2

我在編譯時使用aspectj maven plugin來編織Aspects。當我運行應用程序時,帶有@Advice註釋的類正在第一次調用通知之前被實例化。例如:單元測試編譯時編織

@Aspect 
public class MyAdviceClass { 

    public MyAdviceClass() { 
     System.out.println("creating MyAdviceClass"); 
    } 

    @Around("execution(* *(..)) && @annotation(timed)") 
    public Object doBasicProfiling(ProceedingJoinPoint pjp, Timed timed) throws Throwable { 
     System.out.println("timed annotation called"); 
     return pjp.proceed(); 
    } 
} 

如果非要使用@Timed註解的方法,該「創造MyAdviceClass」將被印刷在第一時間調用該方法,將被印刷的「稱爲定時註釋」的每一次。

我想通過模擬MyAdviceClass中的某些組件來單元測試通知的功能,但不能這樣做,因爲MyAdviceClass僅由AspectJ實例化,而不是通過Spring Beans。

單元測試的最佳實踐方法是什麼?

+0

通常單元測試涉及嘲笑外部依賴,但我沒有看到任何。我猜你想嘲笑一些外部依賴?或者你想嘲笑建議? – Taylor

+0

使用其構造函數創建一個'MyAdviceClass'實例,爲'ProceedingJoinPoint'和'Timed'使用mocks? – 2014-02-12 19:59:52

+0

@泰勒,爲了簡單起見,我排除了他們。 @RC。,你是對的,我可以用這種方式測試'doBasicProfiling'方法,但是我也想測試一下,當我執行一個帶註釋的方法時,這個通知會被調用。 – tgrosinger

回答

0

我找到了解決方案,並希望將其發佈給任何遇到此問題的人。訣竅是在spring bean定義中使用factory-method="aspectOf"。因此,使用上面的例子,我想這行添加到我的applicationContext.xml

<bean class="com.my.package.MyAdviceClass" factory-method="aspectOf"/> 

任何我的單元測試會是這個樣子:

@RunWith(SpringJUnit4ClassRunner.class) 
@ContextConfiguration(locations = "classpath:/META-INF/spring/applicationContext.xml") 
public class MyAdviceClassTest { 
    @Autowired private MyAdviceClass advice; 
    @Mock private MyExternalResource resource; 

    @Before 
    public void setUp() throws Exception { 
     initMocks(this); 
     advice.setResource(resource); 
    } 

    @Test 
    public void featureTest() { 
     // Perform testing 
    } 
} 

更多詳細信息,請here