spring-boot-maven-plugin v3.1.0 OpenJDK 20
When I put an @SpringBootApplication annotated class into the test folder src/test/java and activate useTestClasspath the class cannot be loaded in start goal.
[INFO] --- spring-boot-maven-plugin:3.1.0:start (start-apidoc-application) @ mymodule ---
[INFO] Attaching agents: []
Fehler: Hauptklasse de.my.OpenApiApplication konnte nicht gefunden oder geladen werden
Ursache: java.lang.ClassNotFoundException: de.my.OpenApiApplication
I have verified that the compiled class is present at target/test-classes/de.my. Putting the package and the class to src/main/java works.
pom.xml
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<version>3.1.0</version>
<configuration>
<useTestClasspath>true</useTestClasspath>
<mainClass>de.my.OpenApiApplication</mainClass>
</configuration>
<executions>
<execution>
<id>start-apidoc-application</id>
<phase>prepare-package</phase>
<goals>
<goal>start</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
The docs state in https://docs.spring.io/spring-boot/docs/current/maven-plugin/reference/htmlsingle/#goals-start-parameters-details-useTestClasspath
Flag to include the test classpath when running.
I would expect target/test-classes to be part of the test classpath so the classesthere should be taken into account.
Comment From: wilkinsona
Looking at the original PR, it was intentional that only test dependencies are included. That said, the PR cites Jetty's Maven plugin as a source of inspiration and even around the time of Jetty 7 it has a property named useTestScope that includes test classes and dependencies:
<useTestScope> – If true, the classes from
and dependencies of scope "test" are placed first on the classpath. By default this is false
That continues to be the case in Jetty 11.
The new test-run goal the we added in 3.1 always includes test classes on the classpath. If we change the behavior of useTestClasspath to do that too, run using the test classpath would overlap with test-run.
I'd like to discuss this with the rest of the team. We need to decide:
- if
startshould include test classes on the classpath whenuseTestClasspathistrue. - if
runshould include test classes on the classpath whenuseTestClasspathistrueor if we should deprecate itsuseTestClasspathsetting in favor oftest-run. - if we should treat any changes that we decide to make as a bug or as an enhancement.
Comment From: fjakop
Maybe a little more background for the use case:
We generate the openapi specs from our application with the springdoc-maven-plugin, so we need a startet, yet not blocking, application therefore run is not useable here.
Since we do not like to bootstrap all application layers (services, repositories), which would require a full-blown application.yaml and maybe external systems, we just like to fire up the rest layer and mock all dependency beans. This works very well when placing a stripped down starter class in the test classpath, since we can use mockito for the purpose of mocking the dependency beans.
Comment From: philwebb
Given that we think the current behavior is intentional, we think we should add a new feature to support more options. We think it will be possible to have <useTestClasspath>true</useTestClasspath> and <useTestClasspath>false</useTestClasspath> work for back compatibility but also introduce an enum for different modes. We'd have something like OFF, DEPENDENCIES and ALL for the various different modes.
Comment From: pbarton-andovercos
Have you all thought about maybe adding two more goals: test-start in the pre-integration-test phase and test-stop in the post-integration-test phase to align with the new test-run goal? This would align with the start, run, stop goals but for tests that use a main() for a Local Launcher in testClassesDirectory.
package my.api.tests;
import my.api.MyApplication;
import my.api.tests.config.TestContainerConfiguration;
import org.springframework.boot.SpringApplication;
public class LocalMyApplication {
public static void main(String[] args) {
SpringApplication.from(MyApplication::main)
.with(TestContainerConfiguration.class)
.run(args);
}
}
The test-run goal works great with testcontainers, however we cannot use this inside the build lifecycle as we cannot stop it automatically.