Как бороться с относительным путем в 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