Problem running tests with enabled preview features in surefire and failsafe

This works for me:

  • mvn clean install works (with junit tests)
  • IDEA recognizes module language level correctly as 12 (Preview) - Switch expressions
  • junit tests in IDEA work
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.8.1</version>
        <configuration>
            <release>12</release>
            <compilerArgs>
                <arg>--enable-preview</arg>
            </compilerArgs>
        </configuration>
    </plugin>
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <version>2.22.2</version>
        <configuration>
            <argLine>--enable-preview</argLine>
        </configuration>
    </plugin>

Environment:

  • Ubuntu 18.04.3 x64

  • IDEA 2019.2.1

  • Maven 3.6.0

  • jdk:

     IMPLEMENTOR="Oracle Corporation"
     JAVA_VERSION="12"
     JAVA_VERSION_DATE="2019-03-19"
    

ADDITION: Similarly this approach works for java 13.

ADDITION: Similarly this approach works for java 17.


There are two solutions:

Add --enable-preview to MAVEN_OPTS environment variable.

Explanation by the maintainer of surefire:

The argLine does what it has to do without any issue. The plugin runs JUnit filter which finally selects relevant classes to run in one or multiple JVMs. So the JUnit engine runs twice. Once in plugin JVM, and second in the forked JVM.

Due to the classes are compiled with different major or minor version (in bytecode of *.class files) than the version of Java runtime supports in Maven, this JRE fails because Java in Maven does not understand the bytecode. So, it is curious that the same JVM (javac) produced two major versions depending on JVM option and java from the same JVM does not understand it been incompatible for itself. Although version in forked JVM is totally fine and understands the the classes compiled by javac because javac and forked JVM start with the same option --enable-preview. It is the same situation as if you compiled your sources with Java 12 by maven-compiler-plugin using the toolchain and run the whole Maven build with Java 11. So the classes would be compiled with higher version (in bytecode) than the JRE could understand in Maven process.

We have a wish to rework providers and perform the filtering inside of the forked JVM but this is very compilicated change and still questionary.

The issue is that I used forkCount, it appears surefire doesn't pass parameters to JVM run in fork.

Remove the forkCount parameter from surefire/failsafe configuration.

This will of course cause the tests to run in a single JVM, so if you wanted to speed up the tests using the forks, it won't work now.


Add a configuration for surefire and failsafe maven plugin

<plugin>
   <artifactId>maven-surefire-plugin</artifactId>
    <configuration>
        <argLine>--enable-preview</argLine>
    </configuration>
</plugin>
<plugin>
    <artifactId>maven-failsafe-plugin</artifactId>
    <configuration>
        <argLine>--enable-preview</argLine>
    </configuration>
</plugin>