This plugin works fine to spawn a new H2 DB with tcp mode before integration tests (the default plugin phase): h2-maven-plugin on github
It is not well documented but you can check the Mojo sources to know the configuration options. It is published on maven central.
Basically, for integration tests, you may want Maven to:
- Reserve randomly available network ports, for your Tomcat server, and your H2 (to avoid port conflicts)
- Start the H2 server
- Start the Tomcat server
- Run integration tests
- Stop the Tomcat server
- Stop the H2 server
This can be achieved with a Maven configuration looking like this.
Assuming your integration tests are annoted with a custom interface JUnit Category:
@Category(IntegrationTest.class)
This Maven configuration works fine for me:
<profile>
<id>it</id>
<build>
<plugins>
<!-- Reserve randomly available network ports -->
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<executions>
<execution>
<id>reserve-network-port</id>
<goals>
<goal>reserve-network-port</goal>
</goals>
<phase>process-resources</phase>
<configuration>
<portNames>
<portName>tomcat.test.http.port</portName>
<portName>h2.test.tcp.port</portName>
</portNames>
</configuration>
</execution>
</executions>
</plugin>
<!-- Start H2 before integration tests, accepting tcp connections on the randomly selected port -->
<plugin>
<groupId>com.edugility</groupId>
<artifactId>h2-maven-plugin</artifactId>
<version>1.0</version>
<configuration>
<port>${h2.test.tcp.port}</port>
</configuration>
<executions>
<execution>
<id>Spawn a new H2 TCP server</id>
<goals>
<goal>spawn</goal>
</goals>
</execution>
<execution>
<id>Stop a spawned H2 TCP server</id>
<goals>
<goal>stop</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Start Tomcat before integration tests on the -->
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<configuration>
<systemProperties>
<spring.profiles.active>integration_tests</spring.profiles.active>
<httpPort>${http.test.http.port}</httpPort>
<h2Port>${h2.test.tcp.port}</h2Port>
</systemProperties>
<port>${http.test.http.port}</port>
<contextFile>src/main/java/META-INF/tomcat/webapp-test-context-using-h2.xml</contextFile>
<fork>true</fork>
</configuration>
<executions>
<execution>
<id>run-tomcat</id>
<phase>pre-integration-test</phase>
<goals>
<goal>run</goal>
</goals>
</execution>
<execution>
<id>stop-tomcat</id>
<phase>post-integration-test</phase>
<goals>
<goal>shutdown</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>${h2.version}</version>
</dependency>
</dependencies>
</plugin>
<!-- Run the integration tests annotated with @Category(IntegrationTest.class) -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<!-- Bug in 2.12.x -->
<version>2.11</version>
<dependencies>
<dependency>
<groupId>org.apache.maven.surefire</groupId>
<artifactId>surefire-junit47</artifactId>
<version>2.12.4</version>
</dependency>
</dependencies>
<configuration>
<groups>com.mycompany.junit.IntegrationTest</groups>
<failIfNoTests>false</failIfNoTests>
<junitArtifactName>junit:junit-dep</junitArtifactName>
<systemPropertyVariables>
<httpPort>${tomcat.test.http.port}</httpPort>
<h2Port>${h2.test.tcp.port}</h2Port>
</systemPropertyVariables>
</configuration>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
You may want to use maven filters on the tomcat context file so that the port is replaced:
<contextFile>src/main/java/META-INF/tomcat/webapp-test-context-using-h2.xml</contextFile>
With the file content being:
<Resource name="jdbc/dataSource"
auth="Container"
type="javax.sql.DataSource"
maxActive="100"
maxIdle="30"
maxWait="10000"
username=""
password=""
driverClassName="org.h2.Driver"
url="jdbc:h2:tcp://localhost:${h2.test.tcp.port}/mem:db;DB_CLOSE_ON_EXIT=FALSE;MODE=MySQL"/>
Or if you don't want a JNDI datasource, you can use a Spring declared dataSource, using the the same property...
One extra trip if you want to be able to setup your integration tests tomcat, and run the integration tests from your IDE:
You can use use a property to fork or not the Tomcat server:
<fork>${integrationTestsForkTomcatJvm}</fork>
When you set fork=false, the server will block and maven won't continue, so the integration tests won't be run, but you will be able to run them from your ide.