从Maven启动H2数据库服务器?

假设我想为我的集成testing创build和使用H2数据库。

Maven有一个运行testing的命令: mvn test

有没有办法告诉maven启动H2数据库服务器进行testing,并在完成时停止它?

我想像这个工作类似于我可以通过Maven命令( mvn tomcat:runmvn tomcat:run

对不起,如果这个问题是荒谬的,我仍然围绕着新的概念。

我可以在不使用外部服务器的情况下正常工作,只需通过Maven添加依赖到H2,然后使用这个bean:

 <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="org.h2.Driver"/> <property name="url" value="jdbc:h2:file:h2\db"/> <property name="username" value="sa"/> <property name="password" value=""/> </bean> 

然后再次,这需要我使用基于文件的数据库,而不是在内存中。 但它是诀窍。

您可以使用主要方法创build2个小类,以启动和停止数据库。 这个想法是在运行集成testing之前运行StartServer类,然后在运行testing之后运行类StopServer。

你应该对你的数据库服务器执行相同的操作,如本文档中所描述的那样(描述是为了在集成testing中启动和停止Jetty)

在您的pom.xml中,您应该定义maven-exec-plugin来运行exec:java目标并创build2个执行(1个用于调用StartServer,1个用于StopServer):

 <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>exec-maven-plugin</artifactId> <version>1.1.1</version> <executions> <execution> <!-- start server before integration tests --> <id>start</id> <phase>pre-integration-test</phase> <goals> <goal>java</goal> </goals> <configuration> <mainClass>com.foo.StartServer</mainClass> </configuration> </execution> <execution> <!-- stop server after integration tests --> <id>stop</id> <phase>post-integration-test</phase> <goals> <goal>java</goal> </goals> <configuration> <mainClass>com.foo.StopServer</mainClass> </configuration> </execution> </executions> </plugin> 

希望这就是你想要的

这个插件工作正常,在集成testing(默认插件阶段)之前产生一个新的H2数据库与tcp模式: h2-maven-plugin on github

它没有很好的logging,但你可以检查Mojo的来源知道configuration选项。 它在Maven中心发布。


基本上,对于集成testing,您可能希望Maven:

  • 预留随机可用的networking端口,用于Tomcat服务器和H2(避免端口冲突)
  • 启动H2服务器
  • 启动Tomcat服务器
  • 运行集成testing
  • 停止Tomcat服务器
  • 停止H2服务器

这可以通过一个像这样的Mavenconfiguration来实现。 假设您的集成testing使用自定义接口JUnit类别进行注释:

 @Category(IntegrationTest.class) 

这个Mavenconfiguration适合我:

 <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> 

您可能希望在tomcat上下文文件上使用mavenfilter,以便replace端口:

  <contextFile>src/main/java/META-INF/tomcat/webapp-test-context-using-h2.xml</contextFile> 

随着文件内容是:

  <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"/> 

或者如果你不想要一个JNDI数据源,你可以使用Spring声明的dataSource,使用相同的属性…


如果您希望能够设置您的集成testingtomcat,并且从您的IDE运行集成testing:

你可以使用一个属性来fork或不Tomcat服务器:

 <fork>${integrationTestsForkTomcatJvm}</fork> 

当你设置fork = false时,服务器将被阻塞,maven将不会继续运行,所以集成testing将不会运行,但是你可以从ide运行它们。

我刚刚为maven @ bitbucket启动了H2插件项目。 我将不胜感激任何帮助。

https://bitbucket.org/dohque/maven-h2-plugin

希望这会有帮助。

在我的项目中,对于unit testing,我要求Spring处理这个数据库的创build和初始化。 正如在H2文档中所述,您可以为此创build一个bean:

 <bean id = "org.h2.tools.Server" class="org.h2.tools.Server" factory-method="createTcpServer" init-method="start" destroy-method="stop"> <constructor-arg value="-tcp,-tcpAllowOthers,true,-tcpPort,8043" /> </bean> 

当你开始你的unit testing时,你只需要用这个configuration来启动Spring上下文。

我在unit testing运行之前创build一个基于文件的H2数据库。 该文件位于target目录中,可以随时使用mvn clean进行删除。

我使用maven-sql-plugin如下:

 <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>sql-maven-plugin</artifactId> <version>1.5</version> <dependencies> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <version>1.3.166</version> </dependency> </dependencies> <configuration> <driver>org.h2.Driver</driver> <url>jdbc:h2:file:target/db/testdb</url> <username>sa</username> <password></password> <autocommit>true</autocommit> <skip>${maven.test.skip}</skip> </configuration> <executions> <execution> <id>create-db</id> <phase>process-test-resources</phase> <goals> <goal>execute</goal> </goals> <configuration> <srcFiles> <srcFile>${sql.dir}/drop_db.sql</srcFile> <srcFile>${sql.dir}/tables.sql</srcFile> <srcFile>${sql.dir}/constraints.sql</srcFile> ... etc ... </srcFiles> </configuration> </execution> </executions> </plugin> 

数据库可以通过运行mvn process-test-resources来创build。 运行testing时,确保通过hibernate属性连接到target/db/testdb的数据库。

 <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close" p:driverClassName="org.h2.Driver" p:url="jdbc:h2:file:target/db/testdb" p:username="sa" p:password="" /> 

您还需要依赖maven的依赖项中的com.h2database.h2。

如果你想在内存中,那么只需使用不同的URL:

 <bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource"> <property name="driverClassName" value="org.h2.Driver"/> <property name="url" value="jdbc:h2:mem:db"/> <property name="username" value="sa"/> <property name="password" value=""/> </bean> 

您可以提供其他选项,例如:; DB_CLOSE_DELAY = -1

请参阅: http : //www.h2database.com/html/features.html#in_memory_databases

由于H2不提供Maven插件,所以你应该使用maven-antrun-plugin来启动它。 在ant任务中编写启动和停止h2引擎的代码,并在集成testing开始和停止时调用它。

详见http://docs.codehaus.org/display/MAVENUSER/Maven+and+Integration+Testing

下面是我的工作(只使用h2依赖和exec-maven-plugin ):

  <build> <plugins> <!-- start/stop H2 DB as a server --> <plugin> <groupId>org.codehaus.mojo</groupId> <artifactId>exec-maven-plugin</artifactId> <version>1.2.1</version> <executions> <execution> <id>start-h2</id> <phase>pre-integration-test</phase> <goals> <goal>java</goal> </goals> <configuration> <mainClass>org.h2.tools.Server</mainClass> <arguments> <argument>-tcp</argument> <argument>-tcpDaemon</argument> </arguments> </configuration> </execution> <execution> <id>stop-h2</id> <phase>post-integration-test</phase> <goals> <goal>java</goal> </goals> <configuration> <mainClass>org.h2.tools.Server</mainClass> <arguments> <argument>-tcpShutdown</argument> <argument>tcp://localhost:9092</argument> </arguments> </configuration> </execution> </executions> <configuration> <includeProjectDependencies>true</includeProjectDependencies> <includePluginDependencies>true</includePluginDependencies> <executableDependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> </executableDependency> </configuration> <dependencies> <dependency> <groupId>com.h2database</groupId> <artifactId>h2</artifactId> <version>1.3.173</version> </dependency> </dependencies> </plugin> </plugins> </build> 

请注意,在我的pom.xmlcom.h2database:h2不是项目依赖项。 如果你有它,你可能不需要明确地将其命名为插件依赖项。