2016-12-30 22 views
4

私はCustom AspectのためにJunitテストを書こうとしています。ここでアスペクトクラススニペットは、次のとおりです。AspectJのJUnitテスト

@Aspect 
@Component 
public class SampleAspect { 

    private static Logger log = LoggerFactory.getLogger(SampleAspect.class); 

    @Around("execution(* org.springframework.data.mongodb.core.MongoOperations.*(..)) || execution(* org.springframework.web.client.RestOperations.*(..))") 
    public Object intercept(final ProceedingJoinPoint point) throws Throwable { 
     logger.info("invoked Cutom aspect"); 
     return point.proceed(); 

    } 

} 

jointpointは、ポイントカットが一致するたびしたがって、上記のアスペクトインターセプト。そのうまく動作します。

しかし私の質問は、そのクラスを単体テストする方法です。私は、次のJUnitのテストを持っている:それはポイントカットが一致するようJUnitの中

@Test(expected = MongoTimeoutException.class) 
    public void TestWithMongoTemplate() { 
     //MongoDocument class 
     TestDocument test = new TestDocument(); 

     ApplicationContext ctx = new AnnotationConfigApplicationContext(TestMongoConfigurationMain.class); 
     MongoTemplate mongoTemplate = ctx.getBean(MongoTemplate.class); 

     //this call is being intercepted by SampleAspect 
     mongoTemplate.save(test); 

    } 

だから私のmongoTemplate.save(test)SampleAspectによって傍受されています。しかし、どうすれば私のSampleAspectがジョイントポイントが呼び出されたときにインターセプトしている(おそらく主張することによって)ジュニットで確実にするべきですか?

戻り値がintercept()からアサーションできません。ジョイントポイントを実行する以外は特別なことはありません。ですから、私のJunitは、アスペクトで実行されているのか、戻り値に基づいて定期的に実行されているのかに違いはありません。

任意のコードは、私が何をテストしようとしていることは、アスペクト織りやポイントカットマッチングだと思うprovided.Thanks

答えて

4

場合アスペクトテストの例は素晴らしいことだスニペット。単体テストではなく統合であることに注意してください。あなたが本当にアスペクトロジックを単体テストしたいのであれば、とにかく "mockito"でタグ付けしたので、私はあなたがそれを行うことを提案します:ユニットテストを作成し、アスペクトのジョインポイントを模擬します。ここではいくつかのイントラアスペクトロジックと少し複雑な例である:縦横の標的とされる

Javaクラス:テスト中の

package de.scrum_master.app; 

public class Application { 
    public static void main(String[] args) { 
     new Application().doSomething(11); 
     new Application().doSomething(-22); 
     new Application().doSomething(333); 
    } 

    public void doSomething(int number) { 
     System.out.println("Doing something with number " + number); 
    } 
} 

アスペクト比:

package de.scrum_master.aspect; 

import org.aspectj.lang.ProceedingJoinPoint; 
import org.aspectj.lang.annotation.Around; 
import org.aspectj.lang.annotation.Aspect; 

@Aspect 
public class SampleAspect { 
    @Around("execution(* doSomething(int)) && args(number)") 
    public Object intercept(final ProceedingJoinPoint thisJoinPoint, int number) throws Throwable { 
     System.out.println(thisJoinPoint + " -> " + number); 
     if (number < 0) 
      return thisJoinPoint.proceed(new Object[] { -number }); 
     if (number > 99) 
      throw new RuntimeException("oops"); 
     return thisJoinPoint.proceed(); 
    } 
} 

コンソール実行時のログApplication.main(..)

、側面は11に渡し、あなたが見ることができるように、否定-22および333のために例外をスロー:側面のための

execution(void de.scrum_master.app.Application.doSomething(int)) -> 11 
Doing something with number 11 
execution(void de.scrum_master.app.Application.doSomething(int)) -> -22 
Doing something with number 22 
execution(void de.scrum_master.app.Application.doSomething(int)) -> 333 
Exception in thread "main" java.lang.RuntimeException: oops 
    at de.scrum_master.aspect.SampleAspect.intercept(SampleAspect.aj:15) 
    at de.scrum_master.app.Application.doSomething(Application.java:10) 
    at de.scrum_master.app.Application.main(Application.java:7) 

ユニットテスト:

今、私たちは本当に縦横ことを確認したいです

package de.scrum_master.aspect; 

import org.aspectj.lang.ProceedingJoinPoint; 
import org.junit.Rule; 
import org.junit.Test; 
import org.mockito.Mock; 
import org.mockito.junit.MockitoJUnit; 
import org.mockito.junit.MockitoRule; 

import static org.mockito.Mockito.*; 

public class SampleAspectTest { 
    @Rule 
    public MockitoRule mockitoRule = MockitoJUnit.rule(); 

    @Mock 
    private ProceedingJoinPoint proceedingJoinPoint; 

    private SampleAspect sampleAspect = new SampleAspect(); 

    @Test 
    public void testPositiveSmallNumber() throws Throwable { 
     sampleAspect.intercept(proceedingJoinPoint, 11); 
     // 'proceed()' is called exactly once 
     verify(proceedingJoinPoint, times(1)).proceed(); 
     // 'proceed(Object[])' is never called 
     verify(proceedingJoinPoint, never()).proceed(null); 
    } 

    @Test 
    public void testNegativeNumber() throws Throwable { 
     sampleAspect.intercept(proceedingJoinPoint, -22); 
     // 'proceed()' is never called 
     verify(proceedingJoinPoint, never()).proceed(); 
     // 'proceed(Object[])' is called exactly once 
     verify(proceedingJoinPoint, times(1)).proceed(new Object[] { 22 }); 
    } 

    @Test(expected = RuntimeException.class) 
    public void testPositiveLargeNumber() throws Throwable { 
     sampleAspect.intercept(proceedingJoinPoint, 333); 
    } 
} 

は今ではない、単独でアスペクトロジックをテストするために、この単純なJUnitの+ Mockitoテストを実行します。何それが必要とすべての実行パスをカバーし配線/製織ロジック。後者の場合、別のタイプのテストが必要です。

P.S.:私はJUnitとMockitoを使用しました。通常、私はSpockとその組み込みのモック機能を使用します。 ;-)

+0

これはユニットテストに役立ちました。 @kriegaex。 – karthik

+1

このポストでAspectの統合テストを探している人は、アスペクトでジョインポイントの動作を追跡している属性を作成し、その属性をJunitでアサートしています。それは私のために働いた。 – karthik

+0

実際に、インテグレーションテストを可能にするためだけに、メンバを追加したり、手動で簿記を追加するべきではありません。プロダクションではアスペクトが遅くなります。アスペクトを統合的にテストする方法は他にもたくさんあります。これは別の疑問に値するかもしれません。あなたが1つを作成する場合は、私に通知しないでくださいと私は答えようとします。 – kriegaex