Adam
Adam

Reputation: 5455

mvn spring boot plugin breaks integration testing

My integration testing with maven-failsafe-plugin and JUnit5 was difficult to set up initially, but it now works:

plugins:
  - artifactId: maven-failsafe-plugin
    groupId: org.apache.maven.plugins
    version: 2.19.1
    dependencies:
      - artifactId: junit-platform-surefire-provider
        groupId: org.junit.platform
        version: 1.0.3
      - artifactId: junit-jupiter-engine
        groupId: org.junit.jupiter
        version: 5.1.1
    configuration:
        includes:
          - v3api/*IntegrationTests.java
    executions:
      - goals: [ integration-test, verify ]

However I then want to turn the artifact into a fat jar and it seems as if spring-boot-maven-plugin clashes with maven-failsafe-plugin, because if I put this config into my pom ...

  - artifactId: spring-boot-maven-plugin
    groupId: org.springframework.boot
    version: ${spring.boot.version}
    executions:
      - goals: [ repackage ]
    configuration:
        fork: true
        executable: true
        outputDirectory: ${project.build.directory}/binary

then I get this error instead on integration testing:

Jun 05, 2018 3:03:15 PM org.junit.platform.launcher.core.DefaultLauncher handleThrowable
WARNING: TestEngine with ID 'junit-jupiter' failed to discover tests
java.lang.NoClassDefFoundError: com/adam/api/DbAccess
    at java.lang.Class.getDeclaredMethods0(Native Method)
    at java.lang.Class.privateGetDeclaredMethods(Class.java:2701)
    at java.lang.Class.privateGetPublicMethods(Class.java:2902)
    at java.lang.Class.getMethods(Class.java:1615)
    at org.junit.platform.commons.util.ReflectionUtils.getDefaultMethods(ReflectionUtils.java:1024)
    at org.junit.platform.commons.util.ReflectionUtils.getDeclaredMethods(ReflectionUtils.java:997)
    at org.junit.platform.commons.util.ReflectionUtils.findAllMethodsInHierarchy(ReflectionUtils.java:939)
    at org.junit.platform.commons.util.ReflectionUtils.findMethods(ReflectionUtils.java:923)
    at org.junit.platform.commons.util.ReflectionUtils.findMethods(ReflectionUtils.java:909)
    at org.junit.jupiter.engine.discovery.JavaElementsResolver.resolveContainedMethods(JavaElementsResolver.java:189)
    at org.junit.jupiter.engine.discovery.JavaElementsResolver.resolveChildren(JavaElementsResolver.java:177)
    at java.lang.Iterable.forEach(Iterable.java:75)
    at org.junit.jupiter.engine.discovery.JavaElementsResolver.resolveClass(JavaElementsResolver.java:61)
    at org.junit.jupiter.engine.discovery.DiscoverySelectorResolver.lambda$resolve$3(DiscoverySelectorResolver.java:69)
    at java.util.ArrayList.forEach(ArrayList.java:1249)
    at org.junit.jupiter.engine.discovery.DiscoverySelectorResolver.resolve(DiscoverySelectorResolver.java:68)
    at org.junit.jupiter.engine.discovery.DiscoverySelectorResolver.resolveSelectors(DiscoverySelectorResolver.java:50)
    at org.junit.jupiter.engine.JupiterTestEngine.discover(JupiterTestEngine.java:61)
    at org.junit.platform.launcher.core.DefaultLauncher.discoverEngineRoot(DefaultLauncher.java:130)
    at org.junit.platform.launcher.core.DefaultLauncher.discoverRoot(DefaultLauncher.java:117)
    at org.junit.platform.launcher.core.DefaultLauncher.discover(DefaultLauncher.java:82)
    at org.junit.platform.surefire.provider.TestPlanScannerFilter.accept(TestPlanScannerFilter.java:50)
    at org.apache.maven.surefire.util.DefaultScanResult.applyFilter(DefaultScanResult.java:98)
    at org.junit.platform.surefire.provider.JUnitPlatformProvider.scanClasspath(JUnitPlatformProvider.java:121)
    at org.junit.platform.surefire.provider.JUnitPlatformProvider.invoke(JUnitPlatformProvider.java:111)
    at org.apache.maven.surefire.booter.ForkedBooter.invokeProviderInSameClassLoader(ForkedBooter.java:290)
    at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:242)
    at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:121)
Caused by: java.lang.ClassNotFoundException: com.adam.api.DbAccess
    at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:335)
    at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    ... 28 more

Results :

Tests run: 0, Failures: 0, Errors: 0, Skipped: 0

In the maven spring boot docs they describe how the plugin can be configured to start and stop the spring boot app for integration testing with the pre- and post-integration-testing lifecycle phases.

My app's life cycle is slightly different with a docker and kubernetes aspect. It goes like this:

I have tried binding the spring boot plugin to the package phase, but that makes no difference to the error.

Apart from the spring boot lifecycle phase issue, it could also have a lot to do with JUnit5, because maven-failsafe-plugin seems to be verging on unsupported for JUnit5: How do I run JUnit 5 integration tests with the Maven Failsafe plugin?

i've also seen this on Spring plus JUnit Jupiter but it doesn't help with integration testing.

Upvotes: 3

Views: 1917

Answers (2)

Muel
Muel

Reputation: 4425

The following works for me:

      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
        <version>${springboot.version}</version>
        <executions>
          <execution>
            <!-- repackage will break the integration-test class-path, so schedule after -->
            <phase>post-integration-test</phase>
            <goals>
              <goal>repackage</goal>
            </goals>
          </execution>
        </executions>
      </plugin>

I can run integration tests via: mvn verify

And SpringBoot launches via: java -jar target/my-jar.jar

Upvotes: 5

Norberto Ritzmann
Norberto Ritzmann

Reputation: 419

I've done it using these plugins in hierarchical structure:

Parent
|
 \pom.xml (Added tests plugins including maven-failsafe-plugin)
|
 \ application-startup
   |
    \ pom.xml (Added spring-boot-maven-plugin)

By this way all your subprojects will be tested and only after that maven will assemble in a fat jar.

Upvotes: 1

Related Questions