web-dev-qa-db-fra.com

Contexte d'application de la charge Spring Junit pour les tests

J'ai quelques fichiers XML sous mon répertoire WEB-INF:

  • lyricsBaseApp-servlet.xml
  • hibernate.xml
  • dataSource.xml
  • beans.xml

le servlet xml importe d'autres fichiers xml:

<import resource="dataSource.xml"/>
<import resource="hibernate.xml"/>
<import resource="beans.xml"/>

J'aimerais que ma classe junit4 JukeboxTest inclue la configuration complète du ressort. En utilisant le nom de fichier par défaut, j'ai créé un JukeboxTest-content.xml fichier. Et enfin, je ne sais pas quoi y mettre ...

J'ai essayé:

<import resource="/WEB-INF/dataSource.xml"/>
<import resource="/WEB-INF/hibernate.xml"/>
<import resource="/WEB-INF/beans.xml"/>

ou

<import resource="classpath:./WEB-INF/dataSource.xml"/>
<import resource="classpath:./WEB-INF/hibernate.xml"/>
<import resource="classpath:./WEB-INF/beans.xml"/>

et quelques autres idées, mais toutes ont échoué. Quelqu'un pourrait-il m'indiquer comment accéder à ces fichiers et comment Spring interprète ces chemins de fichiers?

26
ducin

Option 1 (devrait être préférée car c'est la meilleure pratique):
Refactorisez vos fichiers de configuration sous WEB-INF Et déplacez les parties communes (auxquelles vous souhaitez également accéder à partir des tests d'intégration) vers src/main/resources/. Ensuite, écrivez les fichiers de configuration spécifiques au test dans src/test/resources/ (Si vous avez seulement besoin d'importer plusieurs fichiers de configuration différents à partir de src/main Pour assembler votre contexte de test, sautez cela et utilisez @ContextConfiguration De préférence ).

Option 2 (hack):
Utilisez des références telles que:

@ContextConfiguration("file:src/main/webapp/WEB-INF/dataSource.xml")

Option 3 (hack):
Si vous avez un projet Maven, vous pouvez configurer le maven-surefire-plugin (Utilisé dans la phase de test) pour déclarer src/main/webapp Comme élément de chemin de classe supplémentaire pendant l'exécution du test.

Les deux dernières options sont considérées comme du piratage, car les fichiers sous src/main/webapp Ne sont tout simplement pas censés se trouver sur le chemin de classe.

Maintenant l'explication détaillée:

La raison pour laquelle vous ne pouvez pas faire référence à ces fichiers en tant que classpath:/WEB-INF/*.xml Est qu'ils ne sont en effet pas sur le chemin de classe. Il est important de comprendre comment votre webapp est packagée et ce qui finit exactement sur le chemin de classe. En supposant une structure de projet Maven par défaut:

  1. Les classes Java de src/main/Java Vont à /WEB-INF/classes Après la compilation.
  2. Les ressources de src/main/resources Vont également à /WEB-INF/classes.
  3. Les dépendances du projet vont à /WEB-INF/lib.
  4. Tout ce que vous avez dans src/main/webapp Va à / (Racine du paquet). Cela signifie que tous les fichiers de src/main/webapp/WEB-INF Vont bien sûr à /WEB-INF.

La chose la plus importante à savoir est que le chemin de classe ne contiendra que /WEB-INF/classes Et une entrée pour chaque pot dans /WEB-INF/lib. Par conséquent, les ressources en dehors de ces deux emplacements sont complètement invisibles pour le chargeur de classe. Cela est également vrai pour les fichiers de configuration xml directement sous/WEB-INF, C'est pourquoi la référence classpath:/WEB-INF/dataSource.xml Ne fonctionnera jamais.

Vous pouvez vous demander, comment diable sont alors ces fichiers de configuration xml chargés par Spring s'ils ne sont pas accessibles depuis le chemin de classe? La réponse est simple: lorsque vous démarrez votre application Web (au lieu d'exécuter uniquement des tests unitaires/d'intégration), elle s'exécute dans un conteneur de servlets qui donne accès à ServletContext (une classe réelle de l'API Servlet), il utilise donc ServletContext.getResourceAsStream() pour charger ces fichiers. La clé de la compréhension est la citation suivante du javadoc de cette méthode:

Cette méthode est différente de Java.lang.Class.getResourceAsStream, qui utilise un chargeur de classe. Cette méthode permet aux conteneurs de servlets de mettre une ressource à la disposition d'un servlet depuis n'importe quel emplacement, sans utiliser de chargeur de classe.

Désolé, cela devient trop long, mais c'est toute l'histoire ...

83
zagyi

essaye ça

@ContextConfiguration(locations = {"classpath:**/dataSource.xml",
                               "classpath:**/hibernate.xml", 
                               "classpath:**/WEB-INF/beans.xml"})
12
Kris