JUnit에서 src / test / resources 디렉토리의 경로를 얻는 방법?


275

src / test / resources에서 다음을 사용하여 파일을로드 할 수 있다는 것을 알고 있습니다.

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

그러나 어떻게 src / test / resources 디렉토리 의 전체 경로를 얻을 수 있습니까? 즉, 파일을로드하고 싶지 않습니다. 디렉토리의 경로를 알고 싶습니다.


1
호기심에서 : 왜 알고 싶습니까?
fge

3
@fge는 파일을로드하는 데 사용하는 테스트 대상 객체로 전달해야합니다.
Rory

5
리소스 디렉토리에 대한 직접 파일 액세스는 좋지 않습니다. 증기에서 작동하도록 코드를 리팩터링하거나 테스트에서 TemporaryFolder에 사본을 먼저 작성하십시오.
Oliver Charlesworth

4
@OliverCharlesworth 나는 임시 폴더에 대해 항상 동의하고 org.junit.rules.TemporaryFolder항상 사용 합니다 ...하지만 ... 테스트 / 리소스에서 복사하려면 경로를 알아야합니다!
마이크 설치류

1
@ mikerodent-내가 생각한 것은 입력 스트림을 통해 리소스를 읽은 다음 임시 파일에 씁니다.
Oliver Charlesworth

답변:


204

ClassLoader수업 과 협력 해보십시오 .

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

A ClassLoader는 클래스에서로드를 담당합니다. 모든 클래스에는에 대한 참조가 있습니다 ClassLoader. 이 코드는 File리소스 디렉토리에서를 반환합니다 . 호출 getAbsolutePath()하면 절대 값이 리턴 Path됩니다.

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


34
반드시 좋은 생각은 아닙니다. 자원이 항아리 안에 있다면, 이것은 슬픈 시간으로 이어질 것입니다.
Oliver Charlesworth

1
@OliverCharlesworth 그렇다면 항아리의 경우 어떻게 할 수 있습니까?
Anmol Singh Jaggi 7

@AnmolSinghJaggi-원래 질문 아래 내 의견보기 :)
Oliver Charlesworth

이 솔루션을 사용하면 maven 빌드가 실패합니다
firstpostcommenter

파일 이름도 함께있을 것입니다
qwert_ukg

299

클래스 로더를 망칠 필요가 없습니다. 사실 그것은 클래스 로더 자원이기 때문에 들어갈 나쁜 습관 하지 jar 아카이브에있을 때 java.io.File 오브젝트 입니다.

Maven은 테스트를 실행하기 전에 현재 작업 디렉토리를 자동으로 설정하므로 다음을 사용할 수 있습니다.

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

resourcesDirectory.getAbsolutePath() 그것이 실제로 필요한 경우 올바른 값을 반환합니다.

src/test/data테스트에서 파일 시스템을 통해 데이터에 액세스하려면 디렉토리를 작성하는 것이 좋습니다 . 이것은 당신이하고있는 일을 분명히합니다.


4
새 파일 ( "src / test / resources / fileXYZ"); 작동 안 할 것이다. 단순히 JUnit 테스트에 넣는다면 Eclipse 나 Maven이 아닙니다.
seba.wagner

11
Maven에서 잘 작동합니다. 일식에서는 테스트 러너에서 현재 작업 디렉토리를 설정해야하지만 명령 줄 maven 이이 작업을 수행합니다.
Steve C

4
나는 그렇게 생각하지 않습니다. 그리고 왜 "새 파일 (getClass (). getClassLoader (). getResource ("fileNameXYZ.xml ")")을 할 수 있다면 아무 것도 설정하지 않아도됩니다 (Eclipse 또는 Maven).
seba .wagner

10
오히려 빌드 유틸리티의 표준을 따르지 않는 이유는 무엇입니까? 특히 코드를 단순화 할 때. IntelliJ 또는 Maven을 사용하면 작업 디렉토리를 설정할 필요가 없습니다. Eclipse가 항상 고통스럽기 때문에 이것은 가장 간단한 솔루션입니다.
James Watkins

2
IntelliJ 2014 버전의 경우 @Steve C가 언급했듯이 테스트 메소드 / 클래스의 Run / Debug 구성에서 작업 디렉토리를 변경해야했습니다.
a_secenthusiast

76

PathJava 7에서 간단하게 사용합니다.

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

청초한!


이 동일한 코드가 Windows에서 작동합니까? JavaDoc은 Paths.get(...)어쨌든 제안하지 않습니다.
Steve C

@SteveC File.separator상수를 사용하여 경로로 사용될 문자열을 만들 수 있습니다
JeanValjean

1
나는 그것을 알고 있지만 매우 추악합니다. 반대로 new File("src/test/resources")모든 플랫폼에서 올바른 작업을 수행합니다.
Steve C

2
왜 사용하지 Path resourceDirectory = Paths.get("src","test","resources");않습니까?
Navneeth

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

JUnit 4.12 및 Java8을 사용하는 Maven3 프로젝트가 있습니다. myxml.xml아래 에있는 파일의 경로를 얻으려면 src/test/resources테스트 케이스 에서이 작업을 수행하십시오.

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

IntelliJ IDE를 사용하여 Ubuntu 14.04에서 테스트되었습니다. 여기를 참조 하십시오 .


11

의 모든 내용 src/test/resourcestarget/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에 사용됩니다. 이클립스 사용자는 maven 프로젝트도 가져옵니다.) 이것은 작동합니다. IDE를 통해 테스트를 실행할 때 작업 디렉토리가 프로젝트와 동일합니다.
  • 3.1 테스트가 maven 또는
  • (당신은, 당신은 일반적으로 여러 프로젝트를 가져 학생이 아닌 경우) IDE, 하나 개 이상의 프로젝트를 통해 3.2 IDE로 가져, 그리고 당신이 IDE를 통해 테스트를 실행하기 전에, 당신은 수동으로 구성하여 테스트를 위해 작업 디렉토리. 해당 작업 디렉토리는 테스트가 포함 된 가져온 프로젝트를 참조해야합니다. 기본적으로 IDE로 가져온 모든 프로젝트의 작업 디렉토리는 하나입니다. 아마 그것은 IntelliJ IDEA단지 제한 이지만 모든 IDE가 이와 같이 작동한다고 생각합니다. 그리고 수동으로 수행해야하는이 구성은 전혀 좋지 않습니다. 서로 다른 maven 프로젝트에 존재하지만 하나의 큰 "IDE"프로젝트로 가져 오는 여러 테스트를 사용하여이를 기억하고 긴장을 풀고 작업에서 즐거움을 얻지 못하게합니다.

@ ashosborne1에서 제공하는 솔루션 (개인적으로 선호하는 솔루션)에는 테스트를 실행하기 전에 수행해야하는 2 가지 추가 요구 사항이 필요합니다. 이 솔루션을 사용하는 단계 목록은 다음과 같습니다.

  • “src / test / resources /”안에 테스트 폴더 (“teva”)와 파일 (“readme”)을 만듭니다 :

    src / test / resources / teva / readme

    테스트 폴더에 파일을 작성해야합니다. 그렇지 않으면 작동하지 않습니다. Maven은 빈 폴더를 무시합니다.

  • 을 통해 프로젝트를 한 번 이상 빌드하십시오 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 clean을 실행할 때까지 대상 폴더가 삭제됩니다.

IDE를 통해 테스트를 실행하기 전에 테스트 폴더 내에 파일을 작성하고 maven을 처음으로 실행해야합니다. 이 단계가 없으면 IDE에서 테스트 리소스를 만든 다음 IDE를 통해서만 테스트를 작성하고 실행하면 오류가 발생합니다. mvn을 통해 테스트를 실행하면 테스트 리소스가 target / test-classes / teva / readme에 복사되고 클래스 로더가 액세스 할 수있게됩니다.

IDE에서 하나 이상의 메이븐 프로젝트를 가져와야하는 이유와 왜 그렇게 많은 복잡한 것들이 필요한지 묻습니다. 저에게 주요 동기 중 하나는 IDA 관련 파일을 코드에서 멀리 유지하는 것입니다. 먼저 IDE에서 새 프로젝트를 만듭니다. IDE 관련 파일을 보유한 가짜 프로젝트입니다. 그런 다음 기존 Maven 프로젝트를 가져옵니다. 가져온 프로젝트에서 IDEA 파일을 원본 가짜 프로젝트에만 보관하도록 강요합니다. 결과적으로 코드 중에 IDE 관련 파일이 표시되지 않습니다. SVN은 그것들을 보지 않아야합니다 (그러한 파일을 무시하도록 svn / git을 구성하도록 제안하지 마십시오). 또한 매우 편리합니다.


안녕하세요 Alexandr, 대상 / 클래스 및 src / main / resource의 리소스 파일에 문제가 있으며 유일한 이야기 ​​인 것 같습니다. 먼저 src / main / resource에 파일이 있습니다. 프로젝트를 빌드 한 후이 파일을 대상 / 클래스에 복사합니다. 그리고 이것으로부터 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/…를 사용
Alexandr

@ HuyHómHỉnh, 또한 솔루션을 살펴보십시오 : stackoverflow.com/questions/23289098/… 그러나 src / main을 리소스로 구성하려면 그것을 피하십시오.
Alexandr

흠. 무엇이 잘못되었는지 자세히 설명해 주 .gitignore시겠습니까? 또한 테스트를 실행할 때 IDEA가 Maven을 자동으로 실행하는 것처럼 보입니다 (기본적으로 올바른 작업 디렉토리를 설정합니다 $MODULE_DIR$). 따라서 mvn test수동으로 실행할 필요가 없으며 Maven과 IDEA 모두에서 잘 작동합니다 "src/test/resources/somefile.txt".
Alex P.

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

일반적인 경우 테스트를 위해 리소스 폴더의 파일을 사용할 수 없습니다. 리소스 폴더의 리소스 파일이 jar 안에 저장되어 있기 때문입니다. 따라서 파일 시스템에 실제 경로가 없습니다.

가장 간단한 해결책은 다음과 같습니다.

  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

단위 테스트에서 다음을 사용하여 Hibernate with 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

File 객체에서 .getAbsolutePath ()를 사용하십시오.

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

대해서 getFile 반환 문자열 인스턴스가 아닌 파일
마스 Abdrazak

@AlmasAbdrazak GreatDantone은 getFile()파일의 인스턴스 를 반환 한다고 말하지 않습니다 . 그는 그것이 getAbsolutePath()File 객체의 인스턴스에서 사용 된다고 말합니다 .
menteith

@menteith 그의 코드에 따르면, 그는 getFile ()을 호출 한 다음 getFile ()에서 getAbsolutePath ()를 호출하지만 getFile ()은 String을 반환하고 String 객체에서 getAbsolutePath ()를 호출 할 수 없습니다
Almas Abdrazak

0

Spring을 사용하면 resources 폴더 (main / resources 또는 test / resources)에서 쉽게 읽을 수 있습니다.

예를 들어 파일을 작성하십시오. 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;
}

0
List<String> lines = Files.readAllLines(Paths.get("src/test/resources/foo.txt"));
lines.forEach(System.out::println);
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.