45 votes

Comment gérer les chemins relatifs 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 en monModule qui doit ouvrir bar.txt Avec maven, le répertoire de base est le répertoire du module.

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, et non dans celui du module.

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

Existe-t-il un moyen de résoudre ce problème ?

0 votes

Nous vous remercions ! C'était exactement mon problème

84voto

tbruyelle Points 5323

Solution inspirée par Guillaume :

En Run->Edit configuration->Defaults->JUnit->Working directory fixer la valeur $MODULE_DIR$ et Intellij définira le chemin relatif dans tous les junits, tout comme Maven.

0 votes

Parfait ! Vous n'avez pas idée du temps que cela nous a coûté, à moi et à mon équipe.

4 votes

Mais la nouvelle version d'Intellij suggère l'utilisation de l'option MODULE_DIR pour la valeur Working directory champ de texte

0 votes

Le classloading est tellement mieux que le fichier... utiliser le système de fichiers est diabolique

25voto

Guillaume Points 1888

Si vous voulez conserver votre code, vous pouvez essayer de changer le répertoire de travail dans la configuration run/debug (première entrée dans la boîte combo donnant accès à ce que vous voulez exécuter) Définissez-le à la racine de votre module. Mais je préfère l'autre approche suggérée :

ClassLoader.getSystemResourceAsStream(youPath) 

Ou ma préférée :

getClass.getResource(youPath)

ou

getClass.getResourceAsStream(youPath)

Un '/' en tête de chemin indique le répertoire de travail de votre projet, tandis que l'absence de '/' indique un répertoire relatif à la classe actuelle.

J'utilise cette dernière solution pour mes tests : Je place mes ressources de données de test au même niveau de paquetage que la source du test, ou dans un sous-dossier pour éviter un paquetage trop désordonné.

De cette manière, je peux effectuer un simple appel 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 manière :

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

0 votes

J'ai mis le répertoire de travail de junit à $MODULE_DIR$ et cela fonctionne comme prévu. Malheureusement, il n'est pas possible d'utiliser cette variable dans la configuration par défaut de junit ! Quel dommage...

0 votes

$MODULE_DIR$ n'est pas proposé dans la configuration par défaut de junit, mais vous pouvez forcer la valeur dans le champ "working configuration" avec ça marche !

0 votes

@iangreen : Êtes-vous vraiment sûr que c'est le cas - pourriez-vous citer les documents ?

12voto

Sean Patrick Floyd Points 109428

A) N'utilisez pas de fichiers, mais des InputStreams. InputStream via

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

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

b) Ne pas utiliser foo utilisez des répertoires que maven et votre IDE connaissent (c.-à-d. mettez-les dans le répertoire src/main/resources ou src/test/resources Ils se trouvent donc sur le chemin de la classe)

c) Si vous avez une API qui a absolument besoin d'un File et non un InputStream vous pouvez encore le faire

new File(ClassLoader.getSystemResource("foo/bar.xml").toURI())

0 votes

Soyez prudent si vous utilisez groovy dans votre projet : ClassLoader.getSystemResourceAsStream peut cesser de fonctionner (retourner toujours null) parce qu'intellij commence à utiliser un wrapper de ligne de commande / proxy dynamique. Voir pour désactiver cette fonctionnalité jguru.com/faq/view.jsp?EID=1533847 . J'ai perdu tellement d'heures à essayer de comprendre ce qui se passait...

0 votes

Merci, je suis au courant de ces choses, mais j'ai besoin de récupérer un fichier qui ne peut pas être dans le classpath parce que son chemin est configuré dans certains paramètres. J'ai vraiment besoin d'une solution avec un chemin relatif.

2voto

Drew Noakes Points 69288

Vous pouvez spécifier le répertoire de travail du test runner dans la fenêtre Run/Debug Configurations :

enter image description here

0voto

Praveen Points 46

La solution de @tbruyelle fonctionne si vous gardez vos fichiers de projet (.idea) dans le même répertoire que le code source. Si vous choisissez Conserver les fichiers du projet dans ... à un autre endroit, alors $MODULE_DIR$ essaie de chercher dans le répertoire de l'espace de travail et les chemins ne sont pas trouvés. Cela ressemble à un bug d'IntelliJ, j'espère qu'ils le corrigeront bientôt.

Solution de contournement : 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 les projets maven multi-modules, vous n'avez pas le choix, vous devez avoir une configuration d'exécution différente qui pointe 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

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X