Começar um Database Server H2 de Maven?
Pergunta
Suponha que eu queira criar e usar um banco de dados H2 para os meus testes de integração.
Maven tem um comando para executar testes:. mvn test
Existe uma maneira de dizer Maven para iniciar um servidor de banco de dados H2 para os testes e pará-lo quando ele é feito?
Eu imagino que este trabalho semelhante à forma como eu posso correr tomcat através de um comando Maven (mvn tomcat:run
).
Desculpe se esta pergunta é absurda, eu ainda estou quebra minha cabeça em torno de novos conceitos.
Solução
Eu era capaz de fazê-lo funcionar sem o uso de um servidor externo apenas adicionando a dependência de H2 via Maven e depois usar este 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>
Então, novamente, isso exigia que eu uso um DB baseado em arquivo, em vez de in-memory. Mas ele faz o truque.
Outras dicas
Você pode criar 2 classes pequenas com os principais métodos que iniciar e parar o banco de dados. a ideia é executar a classe StartServer antes dos testes de integração são executados e, em seguida, classe stopserver após os testes foram executados.
Você deve fazer o mesmo para o seu servidor de DB como um lugar descrito no este documento (descrição é para iniciar e parar Jetty em testes de integração)
no seu pom.xml você deve definir o maven-exec-plugin para executar o exec: java meta e criar 2 execuções (1 para chamar StartServer e 1 para 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>
esperança de que o que você quer
Este plugin funciona bem para gerar um novo H2 DB com tcp modo antes de testes de integração (o padrão plug-in fase): h2-maven-plugin no github
Não é bem documentado, mas você pode verificar as fontes Mojo conhecer as opções de configuração. É publicada em Central Maven.
Basicamente, para testes de integração, você pode querer Maven para:
- Reserva aleatoriamente disponíveis portas de rede, para o servidor Tomcat, e seu H2 (para evitar conflitos de porta)
- Inicie o servidor H2
- Inicie o servidor Tomcat
- testes de integração executar
- Pare o servidor Tomcat
- Parar o servidor H2
Isto pode ser conseguido com uma configuração Maven com essa aparência. Assumindo que os testes de integração são annoted com uma interface personalizada Categoria JUnit:
@Category(IntegrationTest.class)
Esta configuração Maven funciona bem para mim:
<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>
Você pode querer usar filtros Maven no arquivo de contexto tomcat de modo que a porta é substituído:
<contextFile>src/main/java/META-INF/tomcat/webapp-test-context-using-h2.xml</contextFile>
Com a ser o conteúdo do arquivo:
<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"/>
Ou se você não quer que uma fonte de dados JNDI, você pode usar uma mola declarou dataSource, usando a mesma propriedade ...
Uma viagem extra se você quiser ser capaz de configurar os seus testes de integração tomcat, e executar os testes de integração de seu IDE:
Você pode usar usar uma propriedade para garfo ou não o servidor Tomcat:
<fork>${integrationTestsForkTomcatJvm}</fork>
Quando você conjunto garfo = false, o servidor irá bloquear e maven não vai continuar, assim que os testes de integração não será executado, mas você será capaz de executá-los de seu IDE.
Eu apenas comecei projeto de H2 plugin para o Maven @ bitbucket. Eu aprecio qualquer ajuda com isso.
https://bitbucket.org/dohque/maven-h2-plugin
espero que seja útil.
No meu projeto, para testes de unidade, perguntei Primavera para lidar com esta criação de banco de dados e inicialização. Como se afirma no H2 documentação , você pode criar um feijão para isso:
<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>
Você só precisa iniciar o contexto da Primavera com esta configuração quando você iniciar os testes de unidade.
Eu criar um banco de dados H2 baseado em arquivo antes de testes de unidade são executados. O arquivo fica no diretório target
e pode ser removido a qualquer momento usando mvn clean
.
Eu uso o maven-sql-plugin como segue:
<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>
O banco de dados pode ser criado através da execução mvn process-test-resources
. Quando os testes são executados, certifique-se que você se conectar ao banco de dados em target/db/testdb
via propriedades de hibernação.
<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="" />
Você também vai precisar de uma dependência em com.h2database.h2 nas dependências do Maven.
Se você quiser fazê-lo na memória, então é só usar um URL diferente:
<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>
Você pode dar opções adicionais, tais como:; DB_CLOSE_DELAY = -1
ver: http://www.h2database.com/html/features.html# in_memory_databases
Desde H2 não fornece Maven plug-in você deve iniciá-lo usando maven-antrun-plugin. Escrever código para o motor de arranque e paragem h2 na tarefa formiga e chamá-lo quando o teste é iniciado e integração parada.
detalhes veja no http://docs.codehaus.org/ display / MAVENUSER / Maven + e + Integração + Testing
a seguir faz o trabalho para mim (apenas usando dependência h2
eo 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>
Por favor note, no meu pom.xml
o com.h2database:h2
não era dependência do projeto.
No caso de você tê-lo que você pode não precisa explicitamente nomeá-lo como uma dependência plugin.