Configuration et destruction de l'état de la base de données complexe avec Hibernate / Spring / JUnit

StackOverflow https://stackoverflow.com/questions/822846

  •  03-07-2019
  •  | 
  •  

Question

J'ai une classe de tests unitaires qui nécessite une configuration de base de données assez longue avant l'exécution de chaque méthode de test. Cette configuration prend beaucoup de temps: pour des raisons qui, espérons-le, ne sont pas pertinentes pour la question à traiter, je dois renseigner la base de données par programme plutôt que depuis un cliché SQL.

Le problème que j’ai avec vous est celui du démontage. Comment puis-je annuler facilement toutes les modifications apportées au cours de la phase d’installation de la base de données?

J'utilise actuellement le support des tests transactionnels Hibernate + Spring, de sorte que mes méthodes de test individuelles soient encapsulées dans des transactions.

Une solution serait d’effectuer l’installation de la base de données au sein de chaque méthode de test, de sorte que l’installation de la base de données soit annulée automatiquement. Cependant, l’exécution des méthodes de test prendrait un temps fou puisque chaque méthode aurait besoin de préparer à nouveau la base de données.

Avez-vous d'autres idées? Fondamentalement, je cherche un moyen d'exécuter ma configuration de base de données, d'exécuter mes tests individuels (chacun étant encapsulé dans une transaction annulée après l'exécution), puis d'annuler la configuration initiale de la base de données. Des idées pour que cela fonctionne de manière Hibernate / Spring / Junit? Existe-t-il un Hibernate " supprimer toutes les tables " commande équivalente?

Était-ce utile?

La solution

Êtes-vous coincé avec un fournisseur de base de données spécifique? Sinon, vous pouvez utiliser une base de données en mémoire, telle que HSQLDB . Lorsque vous avez terminé avec les tests, vous venez de jeter l'état. Cela ne convient que si les tables peuvent être vides au début de la suite de tests (c'est-à-dire avant votre configuration par programme).

Vous devez toujours créer des tables, mais si tout est parfaitement mappé avec Hibernate, vous pouvez utiliser hbm2ddl pour générer vos tables. Tout ce que vous avez à faire est d’ajouter ce qui suit à la définition de la fabrique de sessions test :

<session-factory>
    ...
    <property name="hibernate.hbm2ddl.auto">create</property>
    ...
</session-factory>

Si cette solution semble applicable, je peux élaborer.

Autres conseils

Vous pouvez consulter l'annotation @AfterClass pour Junit 4. Cette annotation sera exécutée une fois les tests terminés.

http://cwiki.apache.org/DIRxDEV/junit4-primer.html

DNUnit devrait vous aider à cet égard. Si vous le souhaitez, vous pouvez créer des ensembles de données distincts pour chaque cas de test individuel.

DBUnit aidera beaucoup à cela. Vous pouvez théoriquement désactiver la validation automatique sur JDBC, mais cela va devenir poilu. La solution la plus évidente consiste à utiliser DBUnit pour définir vos données sur un état connu avant d'exécuter les tests. Si, pour une raison quelconque, vous avez besoin de vos données une fois les tests exécutés, vous pouvez consulter @AfterClass dans une suite qui exécute tous vos tests, mais il est généralement considéré comme une meilleure pratique de configurer vos tests, puis de les exécuter. que si le test échoue, ce n’est pas uniquement parce qu’il n’avait pas d’environnement prédéfini en raison de l’échec du nettoyage d’un test différent. Vous vous assurez que chaque test configure directement son environnement.

Une solution que vous pouvez envisager consiste à utiliser un "manuel". annuler ou compenser transaction en db démonter. Je suppose (et si ce n'est pas le cas, il devrait s'agir d'un ajout trivial à vos entités Hibernate), toutes vos entités ont un attribut datetime create indiquant le moment où elles ont été insérées dans la table. Votre méthode de configuration de la base de données devrait enregistrer le temps avant tout. Ensuite, vous avez une procédure assez simple pour la suppression de la base de données afin de supprimer toutes les entités créées après la sauvegarde de la durée dans la configuration de la base de données.

Bien sûr, cela ne fonctionnera pas pour les mises à jour dans la configuration de la base de données ... Mais si vous avez un nombre limité de mises à jour, envisagez de sauvegarder une image vierge pour ce type de données et de la restaurer pendant la suppression de la base de données.

Si vous travaillez avec une base de données relativement petite et avec un SGBD pouvant effectuer des sauvegardes / exportations de celle-ci relativement rapidement (comme MS SQL Server), vous pouvez envisager de créer une sauvegarde de base de données avant les tests, puis de la restaurer lorsque tous les tests sont terminés. Cela vous permet de configurer une base de données de développement / tests et de l’utiliser comme état de départ pour tous vos tests.

Je l’ai fait avec JDBC natif, en exécutant les "sauvegardes de la base de données" et "la restauration de la base de données" entre les tests, et cela a fonctionné assez bien.

Cependant, cette approche dépend du fait que le serveur de SGBD est installé sur votre machine locale (pour une vitesse raisonnable), que vous disposez de privilèges suffisants (ce qui ne devrait pas poser de problème) et que la taille totale de la base de données ne dépasse pas quelques dizaines. MB - du moins d'après mon expérience.

Y a-t-il une raison pour laquelle vous devez disposer d'une connexion à la base de données pour exécuter vos tests unitaires? Il semble qu'il serait peut-être plus facile de refactoriser votre classe afin de pouvoir simuler l'interaction avec la base de données. Vous pouvez simuler des classes (à quelques exceptions près) ainsi que des interfaces avec EasyMock (www.easymock.org).

Si votre classe repose sur un état préexistant complexe dans une base de données connectée, il serait probablement plus facile d'écrire plus rapidement en exécutant des tests à l'aide de mocks. Nous ne savons pas quelle est la taille de votre projet ni à quelle fréquence vos tests sont exécutés, mais le temps d'exécution peut être un sujet de réflexion, en particulier dans le cas d'un projet de grande taille.

Hibernate possède une petite fonctionnalité intéressante, largement sous-documentée et inconnue. Vous pouvez exécuter un script SQL lors de la création de SessionFactory juste après la génération du schéma de base de données pour importer des données dans une nouvelle base de données. Vous devez simplement ajouter un fichier nommé import.sql dans la racine de votre chemin de classe et définir soit créer, soit créer-supprimer comme propriété hibernate.hbm2ddl.auto.

http://in.relation.to/Bloggers/RotterdamJBugAndHibernatesImportsql

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top