Maven + AspectJ / SpringAOP + Lombok + Surefire =在特定情况下测试中断

时间:2015-12-23 15:06:40

标签: maven aspectj spring-aop surefire

我在一个项目中遇到了一个有趣的问题,其中使用了标题中提到的所有技术。我已经能够跟踪诊断(由Surefire准备的测试类路径),但我不明白它是否可以修复以及如何修复。这不是一个表明,对我来说这确实是一个小问题,但无论如何我想解决它。

首先粗略描述。

问题与在项目的特定模块中执行测试有关,并且仅以特定方式执行。

当我从主pom级别运行时,一切正常(测试通过):

cd ${projHome}
mvn install

当我跑步时,一切正常(测试通过):

cd ${projHome}/modules/CoreImplementation/
mvn test

这意味着我可以毫无问题地构建和测试,对于我的Jenkins也是如此,NetBeans可以在需要时从IDE运行测试。

但是当我从主pom级别运行时,该模块未通过测试:

cd ${projHome}
mvn test

出现此错误:

java.lang.NoSuchMethodError: it.tidalwave.northernwind.profiling.RequestProfilerAspect.aspectOf()Lit/tidalwave/northernwind/profiling/RequestProfilerAspect;
    at it.tidalwave.northernwind.frontend.ui.spi.DefaultSiteViewController.processRequest(DefaultSiteViewController.java:82) ~[classes/:na]
    at it.tidalwave.northernwind.frontend.ui.spi.DefaultSiteViewControllerTest.must_call_some_RequestProcessors_when_one_breaks(DefaultSiteViewControllerTest.java:161) ~[test-classes/:na]

作为第二遍(mvn test之后)运行mvn install -DskipTests恰好是Drone.io和Travis完成工作的方式。虽然我可以更改其配置,但我希望保持标准配置并尽可能解决问题。

简短的诊断和我的问题。

现在,问题简短(详情请见下文)。我能够以不同的方式追踪问题,Surefire准备类路径来执行测试。

当我运行mvn install时,类路径为:

${repo}/org/apache/maven/surefire/surefire-booter/2.16/surefire-booter-2.16.jar  
${repo}/org/apache/maven/surefire/surefire-api/2.16/surefire-api-2.16.jar
${projHome}/modules/CoreImplementation/target/test-classes
${projHome}/modules/CoreImplementation/target/classes  
    ${projHome}/modules/Core/target/it-tidalwave-northernwind-core-1.1-ALPHA-37-SNAPSHOT.952b0c8bdc77.jar  
${repo}/it/tidalwave/thesefoolishthings/it-tidalwave-role/3.0-ALPHA-1/it-tidalwave-role-3.0-ALPHA-1.jar  
    ${projHome}/modules/Profiling/target/it-tidalwave-northernwind-core-profiling-1.1-ALPHA-37-SNAPSHOT.952b0c8bdc77.jar  
${repo}/org/apache/commons/commons-math3/3.0/commons-math3-3.0.jar  
…

当我运行mvn test(从项目主页)时,类路径为:

${repo}/org/apache/maven/surefire/surefire-booter/2.16/surefire-booter-2.16.jar
${repo}/org/apache/maven/surefire/surefire-api/2.16/surefire-api-2.16.jar  
${projHome}/modules/CoreImplementation/target/test-classes  
${projHome}/modules/CoreImplementation/target/classes  
    ${projHome}/modules/Core/target/unwoven-classes  
${repo}/it/tidalwave/thesefoolishthings/it-tidalwave-role/3.0-ALPHA-1/it-tidalwave-role-3.0-ALPHA-1.jar  
    ${projHome}/modules/Profiling/target/unwoven-classes
${repo}/org/apache/commons/commons-math3/3.0/commons-math3-3.0.jar  
…

不同的部分是缩进的部分。在前一种情况下,SureFire仅对被测模块使用classes目录(在我的情况下暂时忘记它们unwoven-classes),并为每个依赖项使用已安装的jar文件。在后一种情况下,它似乎是对反应堆中的所有依赖项使用classes

类别路径中的这种差异给我带来麻烦的原因在下面的“血腥细节”一节中解释。简而言之,unwoven意味着它们包含未被AspectJ扩充的字节码,因此是在运行时无法找到的方法。

我正在使用SureFire 2.16,但我也尝试了最新的2.19,没有任何变化。能够强制SureFire 始终使用jar文件的依赖关系将解决我的问题。如果你有答案,你可以在这里停止阅读我的帖子。

血腥细节(仅仅是为了好奇)。

错误模块artifactId为it-tidalwave-northernwind-core-default,它取决于it-tidalwave-northernwind-core-profiling中可用的方面 - 这是违规RequestProfilerAspect所在的位置。方面库依赖关系是故障模块的常规依赖关系和aspectj插件的配置:

<dependency>
  <groupId>it.tidalwave.northernwind</groupId>
  <artifactId>it-tidalwave-northernwind-core-profiling</artifactId>
</dependency>
...
<build>
  <plugins>
    <plugin>
      <groupId>org.codehaus.mojo</groupId>
      <artifactId>aspectj-maven-plugin</artifactId>
      <configuration>
        <aspectLibraries combine.children="append">
          <dependency>
            <groupId>it.tidalwave.northernwind</groupId>
            <artifactId>it-tidalwave-northernwind-core-profiling</artifactId>
          </dependency>
        </aspectLibraries>
      </configuration>
    </plugin>
  </plugins>
</build>

AspectJ集成是通过Super POM中的以下配置文件,在构建中激活,其相关部分是:

<profile>
  <id>it.tidalwave-aspectj-springaop-v1</id>
  ...
  <build>
    <plugins>
      <plugin>
        <artifactId>maven-compiler-plugin</artifactId>
        <executions>
          <execution>
            <id>default-compile</id>
            <phase>compile</phase>
            <configuration>
              <outputDirectory>target/unwoven-classes</outputDirectory>
            </configuration>
          </execution>
          <execution>
            <id>default-testCompile</id>
            <phase>test-compile</phase>
            <configuration>
              <outputDirectory>target/unwoven-test-classes</outputDirectory>
            </configuration>
          </execution>
        </executions>
      </plugin>
      ...

在配置文件中配置了aspectj插件,以便在unwoven-test-classes目录中静态编织二进制文件。这种方法的原因在于它是唯一可行的解​​决方案AFAIK让Lombok和AspectJ一起工作。

现在,回到上面描述的两个类路径:SureFire使用unwoven-classes的事实意味着它指向未使用AspectJ方法扩充的字节码,因此出错。

参考

该项目是一个FLOSS项目,可以在

找到

https://bitbucket.org/tidalwave/northernwind-src

https://github.com/tidalwave-it/northernwind-src

可以重现问题的变更集是f98e9a89ac70138c1b6bd0d4570a22d59ed71be6。构建项目需要JDK 1.8.0(即使它还没有使用Java 8代码)。

可以在这里找到SuperPOM:

https://bitbucket.org/tidalwave/thesefoolishthings-superpom-src

0 个答案:

没有答案