web-dev-qa-db-fra.com

Meilleures pratiques pour les tests JUnit basés sur JPA

C'est une question un peu étrange, mais cela me dérange depuis quelques mois maintenant. J'ai développé une application Web basée sur JPA avec Wicket + Hibernate (construit avec Maven) et je souhaite tester directement la couche DAO. J'ai créé un fichier src/test/resources/META-INF/persistence.xml spécifique que j'ai utilisé pour les tests, mais que j'ai rencontré des conflits avec WTP, etc. Pour contourner ces problèmes, j'ai créé un projet de test distinct hébergeant les tests unitaires. Existe-t-il un meilleur moyen de gérer les tests unitaires pour un projet JPA sans avoir de duels entre fichiers de persistance?

Addendum: Est-ce que d'autres frameworks de test (TestNG, par exemple) faciliteraient cela?

30
mlaccetti

Vous voudrez peut-être essayer mockito . Le test fonctionne comme ceci:

Vous utilisez mockito pour "implémenter" EntityManager. Au lieu du code réel, vous utilisez les méthodes de mockito pour dire "si l'application appelle getReference(), retournez cet objet". En arrière-plan, mockito créera une instance de proxy qui intercepte les appels de méthode Java et renvoie les valeurs que vous spécifiez. Les appels à d'autres méthodes renverront null.

Mimer des choses comme createQuery() fonctionne de la même manière, mais vous devez d'abord créer une maquette de Query, puis utiliser la même approche que dans getReference() (renvoyer la maquette de requête).

Puisque vous n'utilisez pas un vrai EM, vous n'avez pas besoin d'un vrai persistence.xml.

Une solution beaucoup plus simple serait si vous pouviez définir une propriété pour changer le nom du fichier persistence.xml mais je ne pense pas que cela soit possible.

Quelques autres liens qui peuvent aider:

16
Aaron Digulla

Nous utilisons deux fichiers persistence.xml pour la production et les exécutions de tests, mais il s’agit uniquement d’un problème lié au chemin d'accès aux classes (nous utilisons Eclipse mais ne dépendons pas beaucoup des plugins WTP). La seule différence entre les deux est que la version de production ne contient pas de définitions d'entité.

Nous n'utilisons pas de framework moqueur pour tester JPA car cela n'ajouterait aucune valeur à nos tests. Les tests exécutent un véritable accès aux données avec JPA qui communique avec la base de données PostgreSQL.

Notre approche des tests est basée sur le framework de test Spring pour la couche de persistance: les tests en transaction. Notre application est basée sur Spring, mais cette approche est également utilisable pour les applications arbitraires qui souhaitent tirer parti des classes de test Spring. L'essentiel est que chaque test s'exécute au sein d'une transaction unique qui ne soit jamais validée et à la fin (dans tearDown), il est automatiquement annulé. Cela résout le problème de la pollution des données et de la dépendance des tests de manière très discrète et transparente.

La structure de test Spring est flexible pour permettre des tests multi-transaction, mais il s’agit de cas particuliers qui ne constituent pas plus de 10% des tests.

Nous utilisons toujours le support existant pour JUnit 3.8 mais le nouveau Spring TestContext Framework pour JUnit 4 semble très attrayant.

Pour configurer les données de test en transaction, nous utilisons une classe utilitaire interne qui construit des entités commerciales. Étant donné que tous les tests sont partagés, le temps système nécessaire au maintien et à la maintenance est largement dépassé par les avantages de disposer d'un moyen standard et fiable pour configurer les données de test. 

Spring DI aide à rendre les tests concis et auto-descriptifs, mais ce n’est pas une fonctionnalité essentielle.

5
topchef

Utiliser les tests unitaires de Spring et Spring est la meilleure solution. Avec spring, vous n'avez pas besoin de deux persistence.xml car votre persistence.xml ne contient rien, tout est spécifié par spring (tout ce que nous spécifions dans notre persistence.xml est le nom de l'unité de persistance) et vous pouvez donc modifier la configuration de la base etc avec le printemps.

Et comme l'a souligné topchef, les tests unitaires basés sur les transactions de Spring sont excellents. 

4
Michael Wiles

Comme indiqué ici: http://www.devx.com/Java/Article/36785/1954 , Vous pouvez supprimer les lignes suivantes du .settings/org.Eclipse.wst.common.component de votre projet pour éviter de déployer des ressources de test avec l'application Web.

<wb-resource deploy-path="/WEB-INF/classes" source-path="/src/test/Java"/>
<wb-resource deploy-path="/WEB-INF/classes" source-path="/src/test/resources"/>
0
FabienM