web-dev-qa-db-fra.com

Comment gérer le chemin relatif dans Junits entre Maven et Intellij

J'ai un projet maven avec un module

/myProject
pom.xml
    /myModule
    pom.xml
       /foo
       bar.txt

Considérons un Junit dans monModule qui doit ouvrir bar.txt , avec maven the basedir est le répertoire du module.

Donc, pour ouvrir le fichier bar.txt :

  new File("foo/bar.txt")

Cela fonctionne bien lorsque vous exécutez mvn test MAIS lorsque vous lancez le même junit dans intellij, il échoue car Intellij définit le basedir dans le répertoire du projet, pas le répertoire du module.

Intellij essaie d'ouvrir myProject/foo/bar.txt au lieu de myProject/myModule/foo/bar.txt

Y a-t-il un moyen de régler cela?

44
tbruyelle

Si vous souhaitez conserver votre code, vous pouvez essayer de changer le répertoire de travail dans la configuration d'exécution/débogage (première entrée dans la zone de liste déroulante donnant accès à ce que vous voulez exécuter) Définissez-le à la racine de votre module. Mais préférez l'autre approche suggérée:

ClassLoader.getSystemResourceAsStream(youPath) 

Ou mon préféré:

getClass.getResource(youPath)

ou

getClass.getResourceAsStream(youPath)

Un "/" en début de chemin indique le répertoire de travail de votre projet, tandis qu'aucun "/" n'indique un répertoire relatif à la classe actuelle.

J'utilise cette dernière solution pour mes tests: je mets mes ressources de données de test au même niveau de package que la source de test, ou dans un sous-répertoire pour éviter un package trop salissant.

De cette façon, je peux faire un appel simple sans chemin compliqué et sans avoir à gérer le répertoire de travail:

project-root  
  - module A  
    - src  
      - test
        - rootfile.txt  
        - my-complicated-package-naming-root
          - mypackage
            - Test.Java
            - testResource.xml  

Je peux obtenir les fichiers de cette façon:

final URL rootfile= Test.class.getResource("/rootfile.txt");
final URL testResource= Test.class.getResource("testResource.xml");
25
Guillaume

Solution inspirée de Guillaume:

Dans Run->Edit configuration->Defaults->JUnit->Working directory définissez la valeur $MODULE_DIR$ et Intellij définiront le chemin relatif dans toutes les jonctions, tout comme Maven.

84
tbruyelle

a) N'utilisez pas de fichiers, utilisez InputStreams. obtenez votre InputStream via

ClassLoader.getSystemResourceAsStream("foo/bar.xml")

La plupart des API qui traitent des fichiers sont également satisfaites des InputStreams.

b) N'utilisez pas les répertoires foo, utilisez les répertoires maven et votre IDE sachez (c'est-à-dire mettez-les dans src/main/resources ou src/test/resources, donc ils sont sur le chemin de classe)

c) Si vous avez une API qui a absolument besoin d'un File, pas d'un InputStream, vous pouvez toujours faire

new File(ClassLoader.getSystemResource("foo/bar.xml").toURI())
12
Sean Patrick Floyd

Vous pouvez spécifier le répertoire de travail du lanceur de test dans la fenêtre Configurations Exécuter/Déboguer:

enter image description here

2
Drew Noakes

La solution de @tbruyelle fonctionne si vous conservez vos fichiers de projet (.idea) dans le même répertoire que le code source. Si vous choisissez Conserver les fichiers du projet dans ... dans un emplacement différent, alors $ MODULE_DIR $ essaie de rechercher dans le répertoire de l'espace de travail et les chemins sont introuvables. Cela ressemble à un bogue sur IntelliJ, j'espère qu'ils le corrigeront bientôt.

Solution: vous pouvez spécifier le chemin absolu/relatif du module maven dans le répertoire de travail

$MODULE_DIR$/../master/mavenmodule1

$MODULE_DIR$: points to workspace directory
../: relative path to source code
master: root directory of your source code
mavenmodule1: maven module name / directory name of the child module.

Pour le projet maven multi-module, vous n'avez pas le choix, vous devez avoir une configuration d'exécution différente pointant vers ce module. J'aimerais qu'il y ait une autre variable qui pointe juste vers le $ MAVEN_MODULE $ ($ MODULE_DIR $/../master/$ MAVEN_MODULE $) afin que nous puissions utiliser cette configuration pour tous les modules. Pour l'exemple ci-dessus, $ MAVEN_MODULE $ sera remplacé par mavenmodule1

0
Praveen