Як отримати шлях до каталогу src / test / ресурси в JUnit?


275

Я знаю, що можу завантажити файл з src / test / ресурси за допомогою:

getClass().getResource("somefile").getFile()

Але як я можу отримати повний шлях до каталогу src / test / resources , тобто я не хочу завантажувати файл, я просто хочу знати шлях до каталогу?


1
З цікавості: чому ти хочеш це знати?
FGE

3
@fge потрібно передати його тестуваному об'єкту, який використовує його для завантаження файлу
Rory

5
Прямий доступ до файлу до каталогу ресурсів - погана ідея. Refactor ваш код, щоб працювати на пару, або щоб ваш тест створив копію в TemporaryFolder спочатку.
Олівер Чарлсворт,

4
@OliverCharlesworth Я погоджуюся щодо тимчасових папок і використовую org.junit.rules.TemporaryFolderвесь час ... але ... для копіювання з тесту / ресурсів, що вам потрібно знати, е, його шлях!
мійський гризун

1
@mikerodent - я вважаю, що це означало: прочитати ресурс через вхідний потік, а потім записати його у тимчасовий файл.
Олівер Чарлсуорт

Відповіді:


204

Спробуйте працювати з ClassLoaderкласом:

ClassLoader classLoader = getClass().getClassLoader();
File file = new File(classLoader.getResource("somefile").getFile());
System.out.println(file.getAbsolutePath());

A ClassLoaderвідповідає за завантаження в класах. У кожному класі є посилання на а ClassLoader. Цей код повертає a Fileз каталогу ресурсів. Заклик getAbsolutePath()до нього повертає свій абсолют Path.

Javadoc для ClassLoader: http://docs.oracle.com/javase/7/docs/api/java/lang/ClassLoader.html


34
Це не обов'язково гарна ідея. Якщо ресурс знаходиться в банку, це призведе до сумних часів.
Олівер Чарльзворт,

1
@OliverCharlesworth Отже, що можна зробити у випадку з баночкою?
Anmol Singh Jaggi

@AnmolSinghJaggi - Дивіться мій коментар нижче оригінального питання :)
Олівер Чарльзворт

maven build не вдається, коли я використовую це рішення
першеповідомлення

Буде і з назвою файлу
qwert_ukg

299

Вам не потрібно возитися з навантажувачами класу. Насправді, це погана звичка потрапляти, тому що ресурси завантажувача класів не є java.io.File об'єкти, коли вони знаходяться в архіві jar.

Maven автоматично встановлює поточний робочий каталог перед запуском тестів, так що ви можете просто використовувати:

    File resourcesDirectory = new File("src/test/resources");

resourcesDirectory.getAbsolutePath() поверне правильне значення, якщо саме це вам і справді потрібно.

Я рекомендую створити src/test/dataкаталог, якщо ви хочете, щоб ваші тести мали доступ до даних через файлову систему. Це дає зрозуміти, що ви робите.


4
новий файл ("src / test / ресурси / fileXYZ"); не вийде. Ні від Eclipse, ні від Maven, якщо ви просто поклали це на тест JUnit.
seba.wagner

11
Це прекрасно працює від Мейвена. У затемненні вам потрібно буде встановити поточний робочий каталог у тестовому запуску, але командний рядок maven робить це за вас.
Стів C

4
Я не думаю, що так. І навіщо це робити, якщо ви можете просто створити "новий файл (getClass (). GetClassLoader (). GetResource (" fileNameXYZ.xml ")" без необхідності нічого встановлювати. Ні в Eclipse, ні в Maven.
seba .wagner

10
Швидше, чому б ви не дотримувались стандартів утиліти побудови? Особливо, коли це спрощує ваш код. Використовуючи IntelliJ або Maven, не потрібно встановлювати робочий каталог. Це, очевидно, найпростіше рішення, оскільки Eclipse - це біль, як завжди.
Джеймс Уоткінс

2
Для версії IntelliJ 2014 мені довелося все-таки змінити робочий каталог у конфігураціях Run / Debug тестового методу / класу, як було зазначено @Steve C.
a_secenthusiast

76

Я просто використовую Pathз Java 7

Path resourceDirectory = Paths.get("src","test","resources");

Охайно і чисто!


Чи буде такий саме код працювати у Windows? JavaDoc Paths.get(...)пропонує (мені все одно), що він цього не зробить.
Стів C

@SteveC ви можете використовувати File.separatorконстанту для побудови рядка, який буде використовуватися як шлях
JeanValjean

1
Я це знаю, але це дуже некрасиво. Навпаки, new File("src/test/resources")чи робить все правильно на всіх платформах.
Стів C

2
Чому б просто не використовувати Path resourceDirectory = Paths.get("src","test","resources");?
Навнеет

1
Хм, Paths.get("src", "test", "resources")і Paths.get("src/test/resources")мені добре працювати в Windows 10. Що я роблю неправильно? =)
naXa

24

Якщо це весняний проект, ми можемо використовувати код нижче, щоб отримати файли з папки src / test / resource .

File file = ResourceUtils.getFile(this.getClass().getResource("/some_file.txt"));

14

У мене є проект Maven3 за допомогою JUnit 4.12 та Java8. Для того , щоб отримати шлях до файлу під назвою myxml.xmlпід src/test/resources, я роблю це всередині тесту:

@Test
public void testApp()
{
    File inputXmlFile = new File(this.getClass().getResource("/myxml.xml").getFile());
    System.out.println(inputXmlFile.getAbsolutePath());
    ...
}

Тестовано на Ubuntu 14.04 за допомогою IntelliJ IDE. Довідка тут .


11

Весь вміст у програмі src/test/resourcesкопіюється у target/test-classesпапку. Отже, щоб отримати файл з тестових ресурсів під час створення Maven, ви повинні завантажити його з test-classesпапки, наприклад:

Paths.get(
    getClass().getProtectionDomain().getCodeSource().getLocation().toURI()
).resolve(
    Paths.get("somefile")
).toFile()

Зламатися:

  1. getClass().getProtectionDomain().getCodeSource().getLocation().toURI()- дати вам URI target/test-classes.
  2. resolve(Paths.get("somefile"))- вирішує someFileв target/test-classesпапку.

Оригінал anwser узятий з цього


8

Існують відмінності та обмеження у варіантах, пропонованих @Steve C та @ ashosborne1. Вони повинні бути визначені, я вважаю.

Коли ми можемо використовувати File resourcesDirectory = new File("src/test/resources");:?

  • 1 Коли тести будуть проводитися тільки через Maven, але не через IDE.
  • 2.1 Коли тести будуть проводитися через Maven або
  • 2.2 через IDE, і лише один проект імпортується в IDE. (Я використовую "імпортний" термін, тому що він використовується в IntelliJ IDEA. Я думаю, що користувачі eclipse також імпортують свій проект Maven). Це спрацює, тому що робоча директорія, коли ви запускаєте тести через IDE, така сама, як і ваш проект.
  • 3.1 Коли тести будуть проводитися через Maven або
  • 3.2 через IDE, і більше ID проектів імпортується в IDE (коли ви не студент, ви зазвичай імпортуєте кілька проектів) І перед тим, як запустити тести через IDE, ви вручну налаштовуєте робочий каталог для своїх тестів. Цей робочий каталог повинен посилатися на ваш імпортований проект, який містить тести. За замовчуванням робочий каталог усіх проектів, імпортованих у IDE, є лише одним. Можливо, це обмеження IntelliJ IDEAлише, але я думаю, що всі ІДЕ працюють так. І ця конфігурація, яку треба робити вручну, зовсім не є хорошою. Працюючи з декількома тестами, що існують у різних проектах Maven, але імпортовані в один великий проект “IDE”, змушують нас пам’ятати про це і не дозволяють розслабитися та отримати задоволення від вашої роботи.

Рішення, пропоноване @ ashosborne1 (особисто я віддаю перевагу цьому), вимагає 2 додаткових вимог, які необхідно виконати перед запуском тестів. Ось перелік етапів використання цього рішення:

  • Створіть тестову папку ("teva") та файл ("readme") всередині "src / test / ресурси /":

    src / тест / ресурси / teva / readme

    Файл повинен бути створений у тестовій папці, інакше він не працюватиме. Мейвен ігнорує порожні папки.

  • Принаймні один раз створити проект через mvn clean install. Він також запустить тести. Можливо, буде достатньо запустити лише ваш тестовий клас / метод через maven, не будуючи цілого проекту. В результаті ваші тестові ресурси будуть скопійовані в тестові класи, ось такий шлях:target/test-classes/teva/readme

  • Після цього ви можете отримати доступ до папки за допомогою коду, який уже запропонував @ ashosborne1 (Вибачте, що я не зміг правильно відредагувати цей код у цьому списку елементів):

public static final String TEVA_FOLDER = "teva"; ... 
URL tevaUrl = YourTest.class.getClassLoader().getResource(TEVA_FOLDER); 
String tevaTestFolder = new File(tevaUrl.toURI()).getAbsolutePath();

Тепер ви можете запустити свій тест через IDE стільки разів, скільки захочете. Поки ви не запустите mvn чистим. Це випаде цільову папку.

Створення файлу всередині тестової папки та запуску програми Maven вперше, перш ніж запускати тести через IDE, необхідні кроки. Без цих кроків, якщо ви просто у вашій IDE створюєте тестові ресурси, потім пишете тест і запускаєте його лише через IDE, ви отримаєте помилку. Запуск тестів через mvn копіює тестові ресурси в target / test-класи / teva / readme, і вони стають доступними для завантажувача класів.

Ви можете запитати, навіщо мені потрібно імпортувати більше одного проекту Maven в IDE і чому так багато складних речей? Для мене одна з головних мотивацій: тримати файли, пов'язані з IDA, далеко від коду. Спочатку я створюю новий проект у своєму IDE. Це підроблений проект, який є лише власником файлів, пов'язаних з IDE. Потім я імпортую вже існуючі проекти Maven. Я змушую ці імпортовані проекти зберігати файли IDEA лише в моєму первісному підробленому проекті. Як результат, я не бачу серед коду файлів, пов'язаних з IDE. SVN не повинен їх бачити (не пропонуйте налаштувати svn / git на ігнорування таких файлів, будь ласка). Також це дуже зручно.


Привіт Олександре, у мене проблеми з файлом Resource в target / класах та src / main / resource, і ти, здається, єдиний про це говорить. Спочатку у мене є файли на src / main / ресурс, після створення проекту він копіює цей файл у цільовий / клас. І з цього, getClass (). GetClassLoader (). GetResource (fileName) працює лише в цільовій папці, поки я хочу працювати над src / main. Чи можете ви дати мені посилання десь пояснити механізм отримання файлу getResource? як налаштувати папку ресурсів? Tks: D
Huy Hóm Hỉnh

2
@Huy Hóm Hỉnh, я б рекомендував цього не робити. Боюся, ви підете в неправильний бік. Є певні місця, де розміщені файли ресурсів, місця відомі всім іншим. Простіше підтримувати такі проекти. Навіть вам буде легше, вам просто потрібно зрозуміти структуру проектів Maven. Але точно, ви можете налаштувати розташування ресурсів за замовчуванням за допомогою [ maven.apache.org/plugins/maven-resources-plugin/examples/…
Олександр

@ HuyHómHỉnh, Також подивіться на рішення тут: stackoverflow.com/questions/23289098/… Але налаштувати src / main як ресурс ... Спробуйте уникати цього, здається, ви щось зробили не так.
Олександр

хм. Не могли б ви розібратися, у чому справа .gitignore? Крім того, схоже, що IDEA автоматично запускає Maven під час запуску тестів (і встановлює правильний робочий режим за замовчуванням, $MODULE_DIR$). Тому перед цим не потрібно запускати mvn testвручну, все працює нормально і від Maven, і від IDEA "src/test/resources/somefile.txt".
Олексій П.

5

Найпростішим і чистим рішенням, яке я використовую, припустимо, назва тестового класу є TestQuery1і resourcesу вашій testпапці є такий каталог :

├── java
   └── TestQuery1.java
└── resources
    └── TestQuery1
        ├── query.json
        └── query.rq

Щоб отримати URI, TestQuery1виконайте такі дії:

URL currentTestResourceFolder = getClass().getResource("/"+getClass().getSimpleName());

Щоб отримати URI одного з файлів TestQuery1, виконайте:

File exampleDir = new File(currentTestResourceFolder.toURI());
URI queryJSONFileURI = exampleDir.toURI().resolve("query.json");

1
Не хвилюйтесь, адже дякую за допомогу !! Хороша річ, що, видаляючи свою відповідь, я можу видалити питання. Так, досить розчаровано і тут, але все одно дякую !! Добрий вечір :)
Noor

1

Ви не можете використовувати файл із папки ресурсів для тестів у звичайному випадку. Причина полягає в тому, що файли ресурсів у папці ресурсів зберігаються всередині банку. Таким чином, вони не мають реального шляху у файловій системі.

Найбільш простим рішенням може бути:

  1. Скопіюйте файл із ресурсів у тимчасову папку та знайдіть шлях до цього тимчасового файлу.
  2. Робіть тести, використовуючи тимчасовий шлях.
  3. Видаліть тимчасовий файл.

TemporaryFolderfrom JUnitможе бути використаний для створення тимчасових файлів та видалення після тестування. Класи з guavaбібліотеки використовуються для копіювання папки ресурсів форми файлу.

Будь ласка, зауважте, що якщо ми використовуємо підпапку в папці ресурсів, як goodодну, нам не доведеться додавати ведучі /до шляху ресурсу.

public class SomeTest {

    @Rule
    public TemporaryFolder tmpFolder = new TemporaryFolder();


    @Test
    public void doSomethinge() throws IOException {
        File file = createTmpFileFromResource(tmpFolder, "file.txt");
        File goodFile = createTmpFileFromResource(tmpFolder, "good/file.txt");

        // do testing here
    }

    private static File createTmpFileFromResource(TemporaryFolder folder,
                                                  String classLoaderResource) throws IOException {
        URL resource = Resources.getResource(classLoaderResource);

        File tmpFile = folder.newFile();
        Resources.asByteSource(resource).copyTo(Files.asByteSink(tmpFile));
        return tmpFile;
    }

}

0

Використовуйте наступне, щоб ввести в сплячку зі сплячкою Spring у ваших тестах:

@Bean
public LocalSessionFactoryBean getLocalSessionFactoryBean() {
    LocalSessionFactoryBean localSessionFactoryBean = new LocalSessionFactoryBean();
    localSessionFactoryBean.setConfigLocation(new ClassPathResource("hibernate.cfg.xml"));
    localSessionFactoryBean.setPackagesToScan("com.example.yourpackage.model");
    return localSessionFactoryBean;
}

Якщо у вас немає hibernate.cfg.xmlподарунка у вашій src/test/resourcesпапці, він автоматично повернеться до src/main/resourcesпапки у вашій папці.


0

Використовуйте .getAbsolutePath () на своєму об'єкті File.

getClass().getResource("somefile").getFile().getAbsolutePath()

getFile return Строковий екземпляр не FIle
Алмас Абдразак

@AlmasAbdrazak GreatDantone не говорить, що getFile()повертає екземпляр файлу. Він каже, що getAbsolutePath()використовується в екземплярі об'єкта File.
menteith

@menteith Відповідно до свого коду, він викликає getFile (), а потім getAbsolutePath () на getFile (), але getFile () повертає String, і ви не можете зателефонувати getAbsolutePath () на об’єкт String
Almas Abdrazak

0

З Spring ви можете легко прочитати його з папки ресурсів (або основні / ресурси, або тест / ресурси):

Наприклад, створіть файл: test/resources/subfolder/sample.json

@Test
public void testReadFile() {
    String json = this.readFile("classpath:subfolder/sample.json");
    System.out.println(json);
}

public String readFile(String path) {
    try {
        File file = ResourceUtils.getFile(path);
        return new String(Files.readAllBytes(file.toPath()));
    } catch (IOException e) {
        e.printStackTrace();
    }

    return null;
}

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.