Как бороться с относительным путем в Junits между Maven и Intellij

У меня есть проект maven с модулем

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

Рассмотрим Junit в myModule, которому нужно открыть bar.txt, а maven - это каталог модулей.

Итак, чтобы открыть файл bar.txt:

  new File("foo/bar.txt")

Это хорошо работает, когда вы запускаете mvn test НО при запуске одного и того же junit в intellij, он терпит неудачу, потому что Intellij устанавливает baseir в каталоге проекта, а не модуль.

Intellij пытается открыть myProject/foo/bar.txt вместо myProject/myModule/foo/bar.txt

Есть ли способ справиться с этим?

Ответ 1

Если вы хотите сохранить свой код, вы можете попытаться изменить рабочий каталог в конфигурации запуска/отладки (первая запись в поле со списком, обеспечивающая доступ к тому, что вы хотите запустить) Установите это в свой корневой модуль. Но предпочитайте другой предложенный подход:

ClassLoader.getSystemResourceAsStream(youPath) 

Или мое предпочтение:

getClass.getResource(youPath)

или

getClass.getResourceAsStream(youPath)

Ведущий "/" в пути указывает рабочий каталог вашего проекта, а "/" указывает относительный каталог в текущий класс.

Я использую это последнее решение для своих тестов: я помещал свои ресурсы тестовых данных на том же уровне пакета, что и источник теста, или в поддире, чтобы избежать слишком грязного пакета.

Таким образом, я могу сделать простой вызов без сложного пути и не иметь дело с рабочим каталогом:

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

Я могу получить файлы таким образом:

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

Ответ 2

Решение, вдохновленное Гийомом:

В Run->Edit configuration->Defaults->JUnit->Working directory установите значение $MODULE_DIR$, а Intellij установит относительный путь во всех junits точно так же, как Maven.

Ответ 3

a) Не используйте Files, используйте InputStreams. получите InputStream через

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

Большинство API-интерфейсов, которые работают с файлами, также довольны InputStreams.

b) Не используйте каталоги foo, используйте каталоги, о которых знают как maven, так и ваша IDE (т.е. помещают их в src/main/resources или src/test/resources, поэтому они находятся на пути к классу)

c) Если у вас есть API, который абсолютно необходим File, а не InputStream, вы все равно можете

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

Ответ 4

Вы можете указать рабочий каталог для тестового runner в окне Run/Debug Configurations:

введите описание изображения здесь

Ответ 5

Решение от @tbruyelle работает, если вы сохраняете файлы проекта (.idea) в том же каталоге, что и исходный код. Если вы выберете Сохранить файлы проекта в... в другом месте, тогда $MODULE_DIR $пытается найти в каталоге рабочей области, и пути не могут быть найдены. Это похоже на ошибку в IntelliJ, надеюсь, что они исправит ее в ближайшее время.

Обход проблемы: Вы можете указать абсолютный/относительный путь модуля maven в рабочем каталоге

$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.

Для проекта с несколькими модулями maven у вас нет выбора, вам нужно иметь разные конфигурации запуска, указывающие на этот модуль. Мне жаль, что есть еще одна переменная, которая указывает только на $MAVEN_MODULE $($ MODULE_DIR $/../master/$MAVEN_MODULE $), поэтому мы можем использовать эту конфигурацию для всех модулей. В приведенном выше примере $MAVEN_MODULE $будет заменен mavenmodule1