web-dev-qa-db-fra.com

Démarrage d'un serveur de base de données H2 à partir de Maven?

Supposons que je veuille créer et utiliser une base de données H2 pour mes tests d'intégration.

Maven a une commande pour exécuter des tests: mvn test.

Existe-t-il un moyen de dire à maven de démarrer un serveur de base de données H2 pour les tests et de l'arrêter quand c'est fait?

J'imagine que cela fonctionne de la même manière que je peux exécuter Tomcat via une commande Maven (mvn Tomcat:run).

Désolé si cette question est absurde, je suis toujours en train de tourner la tête autour de nouveaux concepts.

37
roufamatic

J'ai pu le faire fonctionner sans utiliser de serveur externe simplement en ajoutant la dépendance à H2 via Maven puis en utilisant ce 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>

Là encore, cela nécessitait que j'utilise une base de données basée sur des fichiers au lieu de la mémoire. Mais ça fait l'affaire.

19
roufamatic

vous pouvez créer 2 petites classes avec les principales méthodes qui démarrent et arrêtent la base de données. l'idée est d'exécuter la classe StartServer avant l'exécution des tests d'intégration, puis la classe StopServer après l'exécution des tests.

vous devriez faire la même chose pour votre serveur DB comme décrit quelque part dans ce document (la description est pour démarrer et arrêter Jetty dans les tests d'intégration)

dans votre pom.xml, vous devez définir le plugin maven-exec pour exécuter l'objectif exec: Java et créer 2 exécutions (1 pour appeler StartServer et 1 pour 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>

j'espère que c'est ce que tu veux

12
Stefan De Boey

Ce plugin fonctionne très bien pour générer une nouvelle base de données H2 avec le mode tcp avant les tests d'intégration (la phase de plugin par défaut): plugin h2-maven sur github

Ce n'est pas bien documenté mais vous pouvez vérifier les sources Mojo pour connaître les options de configuration. Il est publié sur maven central.


Fondamentalement, pour les tests d'intégration, vous souhaiterez peut-être que Maven:

  • Réservez des ports réseau disponibles au hasard, pour votre serveur Tomcat et votre H2 (pour éviter les conflits de ports)
  • Démarrez le serveur H2
  • Démarrez le serveur Tomcat
  • Exécutez des tests d'intégration
  • Arrêtez le serveur Tomcat
  • Arrêtez le serveur H2

Cela peut être réalisé avec une configuration Maven ressemblant à ceci. En supposant que vos tests d'intégration sont annotés avec une interface personnalisée Catégorie JUnit:

@Category(IntegrationTest.class)

Cette configuration Maven fonctionne bien pour moi:

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

Vous pouvez utiliser des filtres maven sur le fichier de contexte Tomcat pour que le port soit remplacé:

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

Le contenu du fichier étant:

  <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 si vous ne voulez pas de source de données JNDI, vous pouvez utiliser une source de données déclarée par Spring, en utilisant la même propriété ...


Un voyage supplémentaire si vous voulez pouvoir configurer vos tests d'intégration Tomcat et exécuter les tests d'intégration à partir de votre IDE:

Vous pouvez utiliser une propriété pour bifurquer ou non le serveur Tomcat:

<fork>${integrationTestsForkTomcatJvm}</fork>

Lorsque vous définissez fork = false, le serveur se bloquera et maven ne continuera pas, donc les tests d'intégration ne seront pas exécutés, mais vous pourrez les exécuter à partir de votre ide.

8
Sebastien Lorber

Je viens de commencer le projet de plugin H2 pour maven @ bitbucket. J'apprécierai toute aide avec elle.

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

J'espère que ce sera utile.

5
Ruslan Pilin

Dans mon projet, pour les tests unitaires, j'ai demandé à Spring de gérer la création et l'initialisation de cette base de données. Comme indiqué dans la documentation H2 , vous pouvez créer un bean pour cela:

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

Il vous suffit de démarrer le contexte Spring avec cette configuration lorsque vous démarrez vos tests unitaires.

4
Romain Linsolas

Je crée une base de données H2 basée sur des fichiers avant d'exécuter les tests unitaires. Le fichier réside dans le répertoire target et peut être supprimé à tout moment à l'aide de mvn clean.

J'utilise le plugin maven-sql comme suit:

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

La base de données peut être créée en exécutant mvn process-test-resources. Lorsque les tests sont exécutés, assurez-vous de vous connecter à la base de données dans target/db/testdb via les propriétés d'hibernation.

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

Vous aurez également besoin d'une dépendance sur com.h2database.h2 dans les dépendances de maven.

4
John Q Citizen

Si vous voulez le faire en mémoire, utilisez simplement une URL différente:

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

Vous pouvez donner des options supplémentaires, telles que:; DB_CLOSE_DELAY = -1

voir: http://www.h2database.com/html/features.html#in_memory_databases

3
fuemf5

Étant donné que H2 ne fournit pas de plugin Maven, vous devez le démarrer en utilisant le plugin maven-antrun. Écrivez le code pour démarrer et arrêter le moteur h2 dans la tâche ant et appelez-le lorsque votre test d'intégration démarre et s'arrête.

Voir les détails sur http://docs.codehaus.org/display/MAVENUSER/Maven+and+Integration+Testing

1
uthark

suit fait le travail pour moi (en utilisant simplement h2 dépendance et 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>

veuillez noter, dans mon pom.xml les com.h2database:h2 n'était pas une dépendance de projet. Dans le cas où vous l'auriez, vous pourriez ne pas avoir besoin de le nommer explicitement en tant que dépendance de plugin.

1
Peter Butkovic