Maven Failsafe is a Maven plugin designed to be used in conjunction with the Maven Surefire Plugin. While the former plugin is intended for running integration tests the latter’s purpose is to run unit tests.
These plugins are tremendously useful for partitioning tests in Maven-based Java applications in order to make tests and builds run faster.
When recently using Maven Failsafe with a Spring Boot application, though, I encountered a somewhat gnarly problem. Running mvn verify
caused this error for all of the application classes (controllers, models etc.) even though those should’ve been on the Java classpath:
1 | java.lang.NoClassDefFoundError: ... Caused by: java.lang.ClassNotFoundException |
Apparently, starting with version 2.19 Maven Failsafe doesn’t use target/classes
as its classpath anymore but the generated JAR file (see Integration Tests With Spring Boot – ClassNotFoundException). When you think about it this does make sense because you want to test against the final build artefact rather than an intermediate directory on your local machine.
However, during the build process Spring Boot (or rather the Spring Boot Maven Plugin) repackages your application into a so-called fat JAR that contains all the dependencies required for running the application. This JAR has a specific internal directory structure with folders such as BOOT-INF
that Maven Failsafe has no chance of figuring out automatically (or generically, considering that Maven Failsafe is intended to be used for Java applications in general, not just Spring Boot ones).
Hence, in order to allow Maven Failsafe to properly recognise our application classes we need to add our target/classes
to its classpath again:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | <pluginmanagement> [...] <plugin> <groupid>org.apache.maven.plugins</groupid> <artifactid>maven-failsafe-plugin</artifactid> <executions> <execution> <goals> <goal>integration-test</goal> <goal>verify</goal> </goals> </execution> </executions> <configuration> <classesdirectory>${project.build.outputDirectory}</classesdirectory> </configuration> </plugin> [...] </pluginmanagement> |
Once that is done Maven Failsafe will work again with your Spring Boot application builds and test runs.
Pingback: Maven Failsafe が java.lang.NoClassDefFoundError で失敗する - JpStack