2013-11-14 5 views
5

Ho diversi aspetti di applicazione della politica AspectJ che sono applicati alla mia directory Maven src/main/java. Recentemente sono stati scoperti dei buchi in questi aspetti, quindi vorrei creare dei test unitari per loro.Esiste un modo intelligente per testare gli aspetti relativi all'applicazione delle policy di AspectJ?

Quello che mi piacerebbe fare è creare file Java nella directory di test (che non è compilato da AspectJ), quindi richiamare programmaticamente il compilatore AspectJ sui file selezionati e fare asserzioni basate sul risultato.

Qualcosa di simile a questo sarebbe perfetto:

assertThat("MyJavaClass.java", producesCompilerErrorFor("SomeAspect.aj")); 

Qualcuno ha fatto qualcosa di simile?

+0

se siete su Windows, AJC è un file batch. basta guardare quella riga di comando ed eseguirla. pensa che tutto ciò di cui hai bisogno è ajtools.jar sul classpath, ma ho dimenticato il nome della classe principale. – aepurniet

+0

Non un'opzione. i test devono essere eseguiti su molti computer diversi su molte piattaforme diverse, senza la necessità per nessuno di installare ajc localmente –

+0

come si pianifica di compilare SomeAspect.aj, senza un compilatore aspectj? – aepurniet

risposta

4

Come al solito, ecco la mia risposta:

ho creato una classe chiamata AbstractAspectJPolicyEnforcementTest. Alcuni dei contenuti sono informazioni proprietarie, ma te lo mostrerò le cose più importanti:

protected Matcher<File> producesCompilationErrorWith(final File aspectFile) { 
    return new AspectJCompilationMatcher(aspectFile, Result.ERROR); 
} 

private class AspectJCompilationMatcher extends TypeSafeMatcher<File> { 
    private final File aspectFile; 
    private final Result expectedResult; 
    private Result result; 

    public AspectJCompilationMatcher(final File aspectFile, final Result expectedResult) { 
     this.aspectFile = aspectFile; 
     this.expectedResult = expectedResult; 
    } 

    @Override 
    protected boolean matchesSafely(final File javaSourceFile) { 
     result = compile(javaSourceFile, aspectFile); 
     return result == expectedResult; 
    } 

    @Override 
    public void describeTo(final Description description) { 
     description.appendText("compilation result: ").appendValue(result); 
    } 
} 

enum Result { 
    ERROR, 
    WARNING, 
    SUCCESS 
} 

private Result compile(final File javaFileName, final File aspectFile) { 

    assertExists(javaFileName); 
    assertExists(aspectFile); 

    List<String> argList = newArrayList(); 

    // java 7 compatibility 
    argList.add("-source"); 
    argList.add("1.7"); 
    argList.add("-target"); 
    argList.add("1.7"); 

    // set class path 
    argList.add("-cp"); 
    argList.add(System.getProperty("java.class.path")); 

    // add java file 
    argList.add(javaFileName.getAbsolutePath()); 

    // add aspect files 
    argList.add(aspectFile.getAbsolutePath()); 
    for (File additionalAspectFile : requiredAspects) { 
     assertExists(additionalAspectFile); 
     argList.add(additionalAspectFile.getAbsolutePath()); 
    } 

    String[] args = argList.toArray(new String[argList.size()]); 
    List<String> fails = newArrayList(); 
    List<String> errors = newArrayList(); 
    List<String> warnings = newArrayList(); 
    List<String> infos = newArrayList(); 

    // org.aspectj.tools.ajc.Main; 
    Main.bareMain(args, false, fails, errors, warnings, infos); 
    if (!fails.isEmpty() || !errors.isEmpty()) { 
     return Result.ERROR; 
    } else if (!warnings.isEmpty()) { 
     return Result.WARNING; 
    } else { 
     return Result.SUCCESS; 
    } 
} 

Ed ecco come lo uso in una classe di test:

public class ForbiddenPackageNameAspectTest extends AbstractAspectJPolicyEnforcementTest { 
    @Test 
    public void testBadPackageName() throws Exception { 
     assertThat(sourceFile(BadJavaClass.class), 
      producesCompilationErrorWith(findAspect("ForbiddenPackageNameAspect"))); 
    } 

    @Test 
    public void testGoodPackageName() throws Exception { 
     assertThat(sourceFile(ForbiddenPackageNameAspectTest.class), 
       compilesWithoutWarningWith(findAspect("ForbiddenPackageNameAspect"))); 
    } 
} 

Naturalmente in una fase successiva , Potrei estendere questo per consentire di verificare specifici messaggi di errore, ma all'inizio lo farò.

1

Ho scritto un framework per isolare ogni aspetto utilizzando Mock e verificare la corrispondenza pointcut. Funziona con chiamate e esecuzione di metodi reali o fittizi.

Forse potrebbe aiutarti.

https://github.com/mock4aj/mock4aj

+0

Bello! Verificherò! –

Problemi correlati