Maven Spring Boot Plugin : how to run spring boot from another project

Filip :

https://docs.spring.io/spring-boot/docs/current/maven-plugin/usage.html

I have a project, with 2 modules.

[Parent]  
|-pom.xml
|  [SpringBoot2App]  
|  |-pom.xml  
|  [test]  
|  |-pom.xml  (start goal here!)

I want to run integration tests (maven failsafe plugin) in a separate project which is another module.

Is is possible to configure the spring boot maven plugin to start/stop the child module, during the integration tests of the parent module?

I tried something like this without success

        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>

            <configuration>

                <mainClass>com.SimpleServiceApplication</mainClass>
                <classesDirectory>../SpringBoot2App/target/classes</classesDirectory>
                <folders>
                     <param>../SpringBoot2App/target/test-classes</param>
                </folders>

            </configuration>
            <executions>
                <execution>
                    <goals>
                        <goal>start</goal>
                    </goals>
                    <phase>pre-integration-test</phase>
                </execution>
            </executions>
        </plugin>

Which does not work.

I also tried to add a "project" parameter after reading the source of the super class of the plugin https://github.com/spring-projects/spring-boot/blob/master/spring-boot-project/spring-boot-tools/spring-boot-maven-plugin/src/main/java/org/springframework/boot/maven/AbstractRunMojo.java

            <configuration> 
                <mainClass>com.SimpleServiceApplication</mainClass>
                <project>${project.parent.collectedProjects[0]}</project>
            </configuration>

This refers to the right project, as debug shows, but does not work either.

Please don't comment on the [0], I know the [0] is not clean and is a coupling that requires direct knowledge of parent pom module ordering.

I get a java.lang.NoClassDefFoundError on org/springframework/boot/SpringApplication

I added the starter-web project to the test pom.xml, same result

ryanp :

I don't think it's possible to run integration tests against another module using spring-boot-maven-plugin, because the start goal doesn't seem to give you a means to resolve the application from the local repository or the Maven reactor, which is probably what you want. The project configuration property you've tried isn't designed to be overriden that way. Plugin executions should be configured using only the properties listed in the plugin goal docs.

Instead I think you've got at least two possible approaches:

  1. Use a different plugin for controlling the server; or
  2. Run the server directly from the tests in code.

Option 1

For this I think you need an approach that copies in the server artifact you want to run, together with something a bit more general for starting and stopping it, like cargo-maven2-plugin or process-exec-maven-plugin.

Just configure the repackage goal in the server artifact build:

<plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <configuration>
        <excludeDevtools>true</excludeDevtools>
    </configuration>
    <executions>
        <execution>
            <goals>
                <goal>repackage</goal>
            </goals>
        </execution>
    </executions>
</plugin>

Then from the integration tests module, you could do something like:

<plugin>
    <artifactId>maven-dependency-plugin</artifactId>
    <executions>
        <execution>
            <id>copy-server-artifact</id>
            <goals>
                <goal>copy</goal>
            </goals>
            <phase>pre-integration-test</phase>
            <configuration>
                <artifactItems>
                    <artifactItem>
                        <groupId>${project.groupId}</groupId>
                        <artifactId>SpringBoot2App</artifactId>
                        <version>${project.version}</version>
                        <classifier>jar</classifier>
                        <outputDirectory>${project.build.directory}</outputDirectory>
                        <destFileName>app.jar</destFileName>
                    </artifactItem>
                </artifactItems>
            </configuration>
        </execution>
    </executions>
</plugin>

<plugin>
    <groupId>com.bazaarvoice.maven.plugins</groupId>
    <artifactId>process-exec-maven-plugin</artifactId>
    <version>0.7</version>
    <executions>
        <execution>
            <id>start-server</id>
            <phase>pre-integration-test</phase>
            <goals>
                <goal>start</goal>
            </goals>
            <configuration>
                <name>run-server</name>
                <waitForInterrupt>false</waitForInterrupt>
                <healthcheckUrl>http://localhost:8080</healthcheckUrl>
                <arguments>
                    <argument>java</argument>
                    <argument>-jar</argument>
                    <argument>${project.build.directory}/app.jar</argument>
                </arguments>
            </configuration>
        </execution>

        <execution>
            <id>stop-server</id>
            <phase>post-integration-test</phase>
            <goals>
                <goal>stop-all</goal>
            </goals>
        </execution>
    </executions>
</plugin>

Option 2

Just declare a normal Maven dependency on the server artifact from the test artifact, and run the server's @SpringBootApplication class in a JUnit before hook or what have you, e.g.

private static ConfigurableApplicationContext context;

@BeforeClass
public static void setUp() {
    context = new SpringApplicationBuilder(SimpleServiceApplication.class).run();
}

@AfterClass
public static void tearDown() {
    if (context != null) {
        context.close();
    }
}

This may be sufficient for your needs.

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=460728&siteId=1