TNG / ArchUnit

A Java architecture test library, to specify and assert architecture rules in plain Java
http://archunit.org
Apache License 2.0
3.19k stars 289 forks source link

Problem with maven multi module project #1308

Closed pelmato closed 4 months ago

pelmato commented 4 months ago

Hi,

I’m not sure whether this is a bug or a misconfiguration.

I have a multi module maven project using maven-jar-plugin to share some test classes between modules. I’ve written a few Archunit tests which are configured to ignore tests classes with new ClassFileImporter().withImportOption(ImportOption.Predefined.DO_NOT_INCLUDE_TESTS).

Everything is OK when I run mvn test but Archunit tests fail when I run mvn verify (failing on Test classes which I expect to be ignored).

I have created a minimalist project to reproduce the problem: https://github.com/pelmato/poc-archunit-ignore-test/tree/main

Is there anything wrong in my example?

Thank you

hankem commented 4 months ago

I'm not a Maven expert, but it seems that mvn verify provides another classpath to the test execution than mvn test does (see also Difference Between “mvn verify” and “mvn test”).

To better understand what's happening, I've extended your class file import with the following debug output:

-    private JavaClasses classesToCheck = new ClassFileImporter()
+    private static JavaClasses classesToCheck = new ClassFileImporter()
+      .withImportOption(location -> {
+           System.out.println(location);
+           return true;
+       })
       .withImportOption(ImportOption.Predefined.DO_NOT_INCLUDE_TESTS)
       .importPackages("com.test");

In addition, you can use the following "test" to see which classesToCheck result from the import:

  @Test void printImportedClasses() {
    classesToCheck.forEach(System.out::println);
  }

These give me

Location{uri=file:./module2/target/test-classes/com/test/module2/GoodByeServiceImplTest.class} (provided by mvn test) is excluded by ImportOption.Predefined.DO_NOT_INCLUDE_TESTS as expected, but Location{uri=jar:file:./module2/target/module2-0.0.1-SNAPSHOT-tests.jar!/com/test/module2/GoodByeServiceImplTest.class} (provided by mvn verify) is kept, and the additional class imported from there makes your test fail.

I guess it can be discussed whether ImportOption.Predefined.DO_NOT_INCLUDE_TESTS should recognize the test-jar or not, but as a workaround for your case, you can add the following custom import option:

      .withImportOption(location -> !location.contains("-tests.jar"))
pelmato commented 4 months ago

Hello @hankem thank you very much for your detailed analysis. The workaround you suggested works fine. I’m going to apply it on the project I’m working on.

Thank you !