web-dev-qa-db-fra.com

Configuration de printemps pour la base de données H2 embarquée pour les tests

À quoi ressemble votre configuration Spring pour les tests d'intégration en utilisant une source de données h2 intégrée et, éventuellement, JUnit?

Mon premier essai avec un SingleConnectionDataSource a fonctionné, mais a échoué sur des tests plus compliqués où vous avez besoin de plusieurs connexions en même temps ou de transactions suspendues. Je pense que h2 dans mode serveur basé sur TCP pourrait également fonctionner, mais ce n'est probablement pas le mode de communication le plus rapide pour une base de données intégrée temporaire en mémoire.

Quelles sont les possibilités et leurs avantages/inconvénients? Aussi, comment créez-vous les tables/remplissez la base de données?


Mise à jour: spécifions certaines exigences concrètes qui sont importantes pour de tels tests.

  • La base de données doit être temporaire et en mémoire
  • La connexion ne devrait probablement pas utiliser TCP, pour des exigences de vitesse
  • Ce serait bien si je pouvais utiliser un outil de base de données pour inspecter le contenu de la base de données pendant le débogage
  • Nous devons définir une source de données car nous ne pouvons pas utiliser la source de données des serveurs d'applications dans les tests unitaires
40
Hans-Peter Störr

Avec la réserve que je ne sais pas s'il existe un outil capable d'inspecter la base de données, je pense qu'une solution simple serait d'utiliser la base de données embarquée Spring ( docs 3.1.x , docs actuels ) qui prend en charge HSQL, H2 et Derby.

En utilisant H2, votre configuration xml ressemblerait à ceci:

<jdbc:embedded-database id="dataSource" type="H2">
    <jdbc:script location="classpath:db-schema.sql"/>
    <jdbc:script location="classpath:db-test-data.sql"/>
</jdbc:embedded-database>

Si vous préférez Java, vous pouvez instancier un DataSource comme ceci (notez que EmbeddedDataBase étend DataSource):

@Bean(destroyMethod = "shutdown")
public EmbeddedDatabase dataSource() {
    return new EmbeddedDatabaseBuilder().
            setType(EmbeddedDatabaseType.H2).
            addScript("db-schema.sql").
            addScript("db-test-data.sql").
            build();
}

Les tables de base de données sont créées par le script db-schema.sql et elles sont remplies avec des données de test de la base de données -test-data.sql script.

N'oubliez pas d'ajouter le pilote de base de données H2 à votre chemin de classe.

48
matsev

J'inclus actuellement dans un fichier springconfig de test uniquement en tant que source de données:

<bean id="database.dataSource" class="org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy">
    <constructor-arg>
        <bean class="org.springframework.jdbc.datasource.SimpleDriverDataSource">
            <property name="driverClass" value="org.h2.Driver" />
            <property name="url"
                value="jdbc:h2:mem:testdb;DB_CLOSE_DELAY=-1;MODE=Oracle;TRACE_LEVEL_SYSTEM_OUT=2" />
        </bean>
    </constructor-arg>
</bean>

<!-- provides a H2 console to look into the db if necessary -->
<bean id="org.h2.tools.Server-WebServer" class="org.h2.tools.Server" 
    factory-method="createWebServer" depends-on="database.dataSource" 
    init-method="start" lazy-init="false">
    <constructor-arg value="-web,-webPort,11111" />
</bean>

La création/suppression des tables peut être effectuée en utilisant executeSqlScript lors de la substitution AbstractAnnotationAwareTransactionalTests.onSetUpBeforeTransaction , ou avec SimpleJdbcTestUtils.executeSqlScript à un endroit approprié.

Comparez aussi cette publication .

18
Hans-Peter Störr

H2 est fourni avec une implémentation de pool de connexions intégrée. Le XML suivant fournit un exemple de son utilisation en tant que bean de source de données sans avoir à introduire de dépendances supplémentaires sur DBCP ou C3P0:

<bean id="dataSource" class="org.h2.jdbcx.JdbcConnectionPool" destroy-method="dispose">
    <constructor-arg>
        <bean class="org.h2.jdbcx.JdbcDataSource">
            <property name="URL" value="jdbc:h2:dbname"/>
            <property name="user" value="user"/>
            <property name="password" value="password"/>
         </bean>
    </constructor-arg>
</bean> 

La base de données sera fermée en appelant une méthode dispose lorsque le contexte de l'application Spring se ferme.

9
ejboy

Je pense qu'il est préférable d'utiliser votre implémentation DataSource de production (uniquement avec une chaîne de connexion différente) pour les tests unitaires.

Quoi qu'il en soit, "l'échec de tests plus compliqués" ne donne pas suffisamment d'informations pour une réponse plus détaillée.

(Auto-annonce: cochez cette case )

0
Bozho