2016-12-30 5 views
4

Ich versuche, Junit Tests für Custom Aspect zu schreiben. Hier ist der Aspekt-Code-Ausschnitt:JUnit Tests für AspectJ

Der obige Aspekt fängt also ab, wenn Gelenkpunkt mit dem Punktschnitt übereinstimmt. Es funktioniert gut.

Aber meine Frage ist, wie diese Klasse Einheit testen. Ich habe folgendes Junit Test:

@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); 

    } 

Also meine mongoTemplate.save(test) in Junit von SampleAspect abgefangen wird, wie es pointcut übereinstimmt. Aber wie soll ich in Junits (wahrscheinlich durch Behauptung) sicherstellen, dass meine SampleAspect abfängt, wenn dieser gemeinsame Punkt aufgerufen wird?

Ich kann nicht auf Rückgabewert von intercept() geltend machen, da es nichts anderes als die Ausführung gemeinsamen Punkt macht. So kann mein Junit keinen Unterschied feststellen, ob er nach Aspekt oder einer regulären Ausführung basierend auf Rückgabewerten ausgeführt wird.

Jeder Code-Schnipsel Beispiele auf Aspekt Testen wäre toll, wenn provided.Thanks

Antwort

4

denke ich, was Sie zu Test versuchen Aspekt Weben und pointcut Matching ist. Bitte beachten Sie, dass dies eher eine Integration als ein Komponententest wäre. Wenn du deine Aspektlogik wirklich testen willst und du die Frage trotzdem mit "Mockito" markiert hast, schlage ich vor, dass du genau das tust: Schreibe einen Komponententest und speichere den Joinpoint des Aspekts und eventuell seine anderen Parameter. Hier ist ein etwas komplexeres Beispiel mit einiger inneren Aspekte Logik:

Java-Klasse von Aspekte ausgerichtet werden:

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); 
    } 
} 

Aspect im Test:

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(); 
    } 
} 

Console Protokoll beim Ausführen Application.main(..):

Wie Sie sehen können, geht der Aspekt am 11. negiert -22 und löst eine Ausnahme für 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) 

Unit-Test für Aspekt: ​​

nun wirklich überprüfen wir, dass der Aspekt wollen tut, was es soll und decken alle Ausführungspfade:

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); 
    } 
} 

jetzt diese einfache JUnit ausführen + Mockito Test, um den Aspekt Logik in Isolation zu testen, nicht die Verdrahtungs-/Weblogik. Für Letzteres benötigen Sie eine andere Art von Test.

S.S .: Nur für dich benutzte ich JUnit und Mockito. Normalerweise verwende ich nur Spock und seine eingebauten Spottfunktionen. ;-)

+0

Das war hilfreich in Unit Testing. @kriegaex. – karthik

+1

Für jeden, der Integrationstest von Aspect in diesem Beitrag sucht - Was ich getan habe, ist, dass ich ein Attribut in dem Aspekt erstellt habe, das das Joinpoint-Verhalten verfolgt, und dann habe ich dieses Attribut in meinem Junit aktiviert.Das hat für mich funktioniert. – karthik

+0

Eigentlich sollten Sie keine Mitglieder oder manuelle Buchhaltung zu einem Aspekt hinzufügen, nur um Integrationstests zu ermöglichen. Es macht den Aspekt in der Produktion langsamer. Es gibt viele andere Möglichkeiten, Aspekte integrativ zu testen. Vielleicht ist das eine andere Frage wert. Wenn Sie eine erstellen, zögern Sie nicht, mich zu benachrichtigen, und ich werde versuchen, zu antworten. – kriegaex

Verwandte Themen