2013-11-14 5 views
5

У меня есть несколько аспектов соблюдения политики AspectJ, которые применяются к моему каталогу Maven src/main/java. Недавно были обнаружены некоторые дыры в этих аспектах, поэтому я хотел бы создать для них модульные тесты.Есть ли разумный способ модульного тестирования аспектов безопасности AspectJ?

Что я хотел бы сделать, это создать файлы Java в тестовом каталоге (который не скомпилирован AspectJ), а затем программным образом вызвать компилятор AspectJ в выбранных файлах и сделать утверждения на основе результата.

Нечто подобное было бы идеально:

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

еще кто-нибудь сделал что-нибудь подобное?

+0

если Youre на окнах, AJC пакетный файл. просто посмотрите на эту командную строку и выполните ее. думаю, все, что вам нужно, это ajtools.jar по пути к классам, но я забыл название основного класса. – aepurniet

+0

Не вариант. тесты должны выполняться на многих разных машинах на разных платформах, без необходимости устанавливать ajc локально –

+0

как вы планируете компилировать SomeAspect.aj без компилятора aspectj? – aepurniet

ответ

4

Как обычно, вот мой собственный ответ:

Я создал класс под названием AbstractAspectJPolicyEnforcementTest. Некоторые из содержания являются служебной информации, но я покажу вам самый важный материал:

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

А вот как я использую его в тестовом классе:

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

Конечно, в следующем шаге , Я мог бы расширить это, чтобы можно было проверить конкретные сообщения об ошибках, но для начала это будет сделано.

1

Я написал структуру, чтобы изолировать каждый аспект с помощью Mocks и проверить соответствие pointcut. Он работает с вызовами и исполнением реальных или фиктивных методов.

Возможно, это может вам помочь.

https://github.com/mock4aj/mock4aj

+0

Ницца! Вы проверите это! –

Смежные вопросы