假设我想为我的集成测试创建和使用 H2 数据库。
Maven 有一个运行测试的命令:mvn test
.
有没有办法告诉 maven 为测试启动 H2 数据库服务器并在完成后停止它?
我想这类似于我通过 Maven 命令 ( mvn tomcat:run
) 运行 tomcat 的方式。
抱歉,如果这个问题是荒谬的,我仍在思考新概念。
只需通过 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>
再说一次,这要求我使用基于文件的数据库而不是内存中的数据库。但它确实有效。
您可以使用启动和停止数据库的主要方法创建 2 个小类。这个想法是在运行集成测试之前运行 StartServer 类,然后在运行测试之后运行 StopServer 类。
您应该对您的数据库服务器执行相同的操作,如本文档某处所述(描述用于在集成测试中启动和停止 Jetty)
在您的 pom.xml 中,您应该定义 maven-exec-plugin 以运行exec:java目标并创建 2 个执行(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>
希望这就是你想要的
这个插件可以很好地在集成测试之前使用 tcp 模式生成一个新的 H2 DB(默认插件阶段):github 上的 h2-maven-plugin
它没有很好的文档记录,但您可以查看 Mojo 源以了解配置选项。它发布在 Maven 中心。
基本上,对于集成测试,您可能希望 Maven:
这可以通过如下所示的 Maven 配置来实现。假设您的集成测试使用自定义接口 JUnit 类别进行注释:
@Category(IntegrationTest.class)
这个 Maven 配置对我来说很好:
<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 上下文文件上使用 maven 过滤器,以便替换端口:
<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 声明的数据源,使用相同的属性...
如果您希望能够设置集成测试 tomcat 并从 IDE 运行集成测试,则需要额外的一趟:
您可以使用属性来分叉或不分叉 Tomcat 服务器:
<fork>${integrationTestsForkTomcatJvm}</fork>
当你设置 fork=false 时,服务器会阻塞,maven 不会继续,所以集成测试不会运行,但是你可以从你的 ide 运行它们。
我在运行单元测试之前创建了一个基于文件的 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
。运行测试时,请确保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。
在我的项目中,为了进行单元测试,我让 Spring 来处理这个数据库的创建和初始化。如H2 文档中所述,您可以为此创建一个 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>
当您开始单元测试时,您只需要使用此配置启动 Spring 上下文。
我刚刚为 maven @ bitbucket 启动了 H2 插件项目。我将不胜感激任何帮助。
https://bitbucket.org/dohque/maven-h2-plugin
希望它会有所帮助。
如果你想在内存中创建它,那么只需使用不同的 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
依赖项和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.xml
的com.h2database:h2
不是项目依赖项中。如果您拥有它,您可能不需要将其显式命名为插件依赖项。
由于 H2 不提供 Maven 插件,因此您应该使用 maven-antrun-plugin 启动它。在 ant 任务中编写启动和停止 h2 引擎的代码,并在集成测试启动和停止时调用它。
请参阅http://docs.codehaus.org/display/MAVENUSER/Maven+and+Integration+Testing上的详细信息