Como obter o caminho do diretório src / test / resources no JUnit?

275

Eu sei que posso carregar um arquivo de src / test / resources com:

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

Mas como posso obter o caminho completo para o diretório src / test / resources , ou seja, não quero carregar um arquivo, apenas quero saber o caminho do diretório?

Rory
fonte
1
Por curiosidade: por que você quer saber?
FGE
3
necessidade @fge passá-lo para objeto sob teste, que a utiliza para carregar um arquivo
Rory
5
O acesso direto a arquivos no diretório de recursos é uma má idéia. Refatore seu código para operar a vapor ou faça com que seu teste crie uma cópia em uma TemporaryFolder primeiro.
Oliver Charlesworth 23/02
4
@OliverCharlesworth Concordo em pastas temporárias e uso org.junit.rules.TemporaryFoldero tempo todo ... mas ... para copiar dos testes / recursos, você precisa saber, er, seu caminho!
mike roedor
1
@mikerodent - o que eu acho que quis dizer foi: leia o recurso através de um inputstream e depois grave-o em um arquivo temporário.
Oliver Charlesworth 27/02

Respostas:

204

Tente trabalhar com a ClassLoaderclasse:

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

A ClassLoaderé responsável pelo carregamento nas aulas. Toda classe tem uma referência a ClassLoader. Este código retorna a Filedo diretório de recursos. Invocá getAbsolutePath()-lo retorna sua absolutaPath .

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

ashosborne1
fonte
34
Isso não é necessariamente uma boa ideia. Se o recurso estiver em um jar, isso levará a momentos tristes.
Oliver Charlesworth 23/02
1
@OliverCharlesworth Então, o que pode ser feito em caso de jar?
Anmol Singh Jaggi
@AnmolSinghJaggi - Ver o meu comentário abaixo a pergunta original :)
Oliver Charlesworth
construção Maven falhar quando eu uso essa solução
firstpostcommenter
Também estará com o nome do arquivo
qwert_ukg 05/10
299

Você não precisa mexer com os carregadores de classes. Na verdade, é um mau hábito entrar porque os recursos do carregador de classes não são objetos java.io.File quando estão em um arquivo jar.

O Maven define automaticamente o diretório de trabalho atual antes de executar os testes, para que você possa usar:

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

resourcesDirectory.getAbsolutePath() retornará o valor correto se é isso que você realmente precisa.

Eu recomendo criar um src/test/datadiretório se você quiser que seus testes acessem dados através do sistema de arquivos. Isso deixa claro o que você está fazendo.

Steve C
fonte
4
novo arquivo ("src / test / resources / fileXYZ"); não funciona. Nem do Eclipse nem do Maven se você simplesmente colocar isso em um teste JUnit.
seba.wagner
11
Funciona muito bem com o Maven. No eclipse, você precisará definir o diretório de trabalho atual no executor de teste, mas a linha de comando maven faz isso por você.
C #
4
Acho que não. E por que você faria isso se pudesse fazer simplesmente um "novo arquivo (getClass (). GetClassLoader (). GetResource (" fileNameXYZ.xml ")") sem a necessidade de configurar nada. Nem no Eclipse nem no Maven.
seba .wagner
10
Em vez disso, por que você não seguiu os padrões do seu utilitário de construção? Especialmente quando simplifica seu código. Usando o IntelliJ ou o Maven, não é necessário definir o diretório de trabalho. Essa é obviamente a solução mais simples, com o Eclipse sendo uma dor, como sempre.
22416 James Watkins
2
Para a versão IntelliJ 2014, eu ainda precisava alterar o diretório de trabalho nas configurações de Execução / Depuração do método / classe de teste, como o @Steve C mencionou.
a_secenthusiast
76

Eu simplesmente usaria Pathdo Java 7

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

Arrumado e limpo!

Jean Valjean
fonte
Esse código exatamente funciona no Windows? O JavaDoc para Paths.get(...)sugere (para mim de qualquer maneira) que não.
Steve C
@SteveC você pode usar File.separatorconstante para construir a string para ser usado como um caminho
Jean Valjean
1
Eu sei disso, mas é muito feio. Por outro lado, new File("src/test/resources")faz a coisa certa em todas as plataformas.
Steve C
2
Por que não usar apenas Path resourceDirectory = Paths.get("src","test","resources");?
Navneeth
1
Hmm, Paths.get("src", "test", "resources")e Paths.get("src/test/resources")funciona bem no Windows 10 para mim. O que estou fazendo de errado? =)
naXa 16/05
24

Se for um projeto de primavera, podemos usar o código abaixo para obter arquivos da pasta src / test / resource .

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

Eu tenho um projeto Maven3 usando JUnit 4.12 e Java8. Para obter o caminho de um arquivo chamado myxml.xmlunder src/test/resources, faço isso de dentro do caso de teste:

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

Testado no Ubuntu 14.04 com IntelliJ IDE. Referência aqui .

Antony
fonte
11

Todo o conteúdo src/test/resourcesé copiado para a target/test-classespasta. Portanto, para obter o arquivo dos recursos de teste durante a compilação do maven, você deve carregá-lo da test-classespasta, assim:

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

Demolir:

  1. getClass().getProtectionDomain().getCodeSource().getLocation().toURI() - fornecer URI para target/test-classes .
  2. resolve(Paths.get("somefile"))- resolve someFilepara a target/test-classespasta.

O analisador original é retirado deste

cereja
fonte
8

Existem diferenças e restrições nas opções oferecidas por @Steve C e @ ashosborne1. Eles devem ser especificados, acredito.

Quando podemos usar File resourcesDirectory = new File("src/test/resources");:?

  • 1 Quando os testes serão executados apenas pelo maven, mas não pelo IDE.
  • 2.1 Quando os testes serão realizados via maven ou
  • 2.2 via IDE e apenas um projeto é importado para o IDE. (Eu uso o termo "importado", porque ele é usado no IntelliJ IDEA. Acho que os usuários do eclipse também importam seu projeto maven). Isso funcionará, pois o diretório de trabalho ao executar testes via IDE é igual ao seu projeto.
  • 3.1 Quando os testes serão realizados via maven ou
  • 3.2 via IDE, e mais de um projeto é importado para o IDE (quando você não é aluno, geralmente importa vários projetos) E antes de executar testes via IDE, você configura manualmente o diretório de trabalho para seus testes. Esse diretório de trabalho deve se referir ao seu projeto importado que contém os testes. Por padrão, o diretório de trabalho de todos os projetos importados para o IDE é apenas um. Provavelmente é apenas uma restrição IntelliJ IDEA, mas acho que todos os IDEs funcionam assim. E essa configuração que deve ser feita manualmente, não é boa. Trabalhando com vários testes existentes em diferentes projetos, mas importados para um grande projeto “IDE”, nos forçamos a lembrar disso e não permitimos relaxar e desfrutar do seu trabalho.

A solução oferecida por @ ashosborne1 (pessoalmente, prefiro este) requer 2 requisitos adicionais que devem ser feitos antes da execução dos testes. Aqui está uma lista de etapas para usar esta solução:

  • Crie uma pasta de teste ("teva") e um arquivo ("leia-me") dentro de "src / test / resources /":

    src / test / recursos / teva / readme

    O arquivo deve ser criado na pasta de teste, caso contrário, não funcionará. Maven ignora pastas vazias.

  • Pelo menos uma vez construa o projeto via mvn clean install. Também executará testes. Pode ser suficiente executar apenas sua classe / método de teste via maven sem criar um projeto inteiro. Como resultado, seus recursos de teste serão copiados para classes de teste, eis um caminho:target/test-classes/teva/readme

  • Depois disso, você pode acessar a pasta usando o código, já oferecido por @ ashosborne1 (desculpe, não foi possível editar esse código dentro desta lista de itens corretamente):

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

Agora você pode executar seu teste via IDE quantas vezes quiser. Até você executar o mvn clean. Ele soltará a pasta de destino.

Criar arquivos dentro de uma pasta de teste e executar o maven pela primeira vez, antes de executar testes via IDE, são etapas necessárias. Sem essas etapas, se você apenas criar no IDE recursos de teste, gravar o teste e executá-lo apenas via IDE, receberá um erro. A execução de testes via mvn copia os recursos de teste para target / test-classes / teva / readme e eles se tornam acessíveis para um carregador de classe.

Você pode perguntar: por que preciso importar mais de um projeto de maven no IDE e por que tantas coisas complicadas? Para mim, uma das principais motivações: manter os arquivos relacionados à IDA longe do código. Primeiro criei um novo projeto no meu IDE. É um projeto falso, que é apenas um detentor de arquivos relacionados ao IDE. Em seguida, importo projetos maven já existentes. Forço esses projetos importados a manter os arquivos IDEA apenas no meu projeto falso original. Como resultado, não vejo arquivos relacionados ao IDE no código. O SVN não deve vê-los (não ofereça configurar o svn / git para ignorar esses arquivos, por favor). Também é apenas muito conveniente.

Alexandr
fonte
Oi Alexandr, estou com problemas com o arquivo de recursos no target / classes e src / main / resource e você parece ser o único a falar sobre isso. Primeiro eu tenho arquivos em src / main / resource, após o projeto de compilação, ele copia esses arquivos para o target / classes. E a partir disso, getClass (). GetClassLoader (). GetResource (fileName) só funciona na pasta de destino enquanto eu quero trabalhar em src / main. Você pode me dar um link em algum lugar para explicar o mecanismo do arquivo getResource? como configurar a pasta de recursos? Tks: D
Huy Hóm Hỉnh
2
@Huy Hóm Hỉnh, eu recomendaria não fazê-lo. Receio que você vá na direção errada. Há certos lugares onde os arquivos de recursos estão localizados, os lugares são conhecidos por todos os outros. Mais fácil de manter esses projetos. Mesmo para você, será mais fácil, você só precisa entender a estrutura dos projetos. Mas com certeza, você pode configurar o local de recurso padrão com [ maven.apache.org/plugins/maven-resources-plugin/examples/...
Alexandr
@ HuyHómHỉnh, também dê uma olhada na solução aqui: stackoverflow.com/questions/23289098/… Mas para configurar o src / main como um recurso ... Tente evitá-lo, parece que você está fazendo algo errado.
Alexandr
hm Você poderia elaborar o que há de errado .gitignore? Além disso, parece que o IDEA executa o Maven automaticamente ao executar testes (e define o diretório de trabalho correto por padrão $MODULE_DIR$). Portanto, não há necessidade de executar mvn testmanualmente antes disso, tudo funciona bem tanto com o Maven quanto com o IDEA "src/test/resources/somefile.txt".
Alex P.
5

A solução mais simples e limpa que eu uso, suponha que o nome da classe de teste seja TestQuery1e exista um resourcesdiretório em sua testpasta da seguinte maneira:

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

Para obter o URI do TestQuery1do:

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

Para obter o URI de um dos arquivos TestQuery1, faça:

File exampleDir = new File(currentTestResourceFolder.toURI());
URI queryJSONFileURI = exampleDir.toURI().resolve("query.json");
Noor
fonte
1
Não se preocupe, de fato, obrigado por sua ajuda! O bom é que, ao excluir sua resposta, sou capaz de excluir a pergunta. Sim, muito frustrado aqui fora também, mas de qualquer forma obrigado !! Boa noite :)
Noor
1

Você não pode usar um arquivo de uma pasta de recursos para testes em um caso comum. O motivo é que os arquivos de recursos na pasta de recursos são armazenados dentro de um jar. Portanto, eles não têm um caminho real no sistema de arquivos.

A solução mais simples pode ser:

  1. Copie um arquivo de recursos para a pasta temporária e obtenha um caminho para esse arquivo temporário.
  2. Faça testes usando um caminho temporário.
  3. Exclua o arquivo temporário.

TemporaryFolderfrom JUnitpode ser usado para criar arquivos temporários e excluí-lo após a conclusão do teste. Aulas deguava biblioteca são usadas para copiar uma pasta de recursos do formulário de arquivo.

Observe que, se usarmos uma subpasta na pasta de recursos, como gooduma, não precisaremos adicionar /o caminho do recurso.

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;
    }

}
v.ladynev
fonte
0

Use o seguinte para injetar o Hibernate with Spring em seus testes de unidade:

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

Se você não tiver o hibernate.cfg.xmlpresente na sua src/test/resourcespasta, ele retornará automaticamente ao da sua src/main/resourcespasta.

sobrancelha branca
fonte
0

Use .getAbsolutePath () no seu objeto File.

getClass().getResource("somefile").getFile().getAbsolutePath()
GreatDantone
fonte
getFile return String instance not FIle
Almas Abdrazak
@AlmasAbdrazak GreatDantone não diz que getFile()retorna uma instância de arquivo. Ele diz que getAbsolutePath()é usado em uma instância do objeto File.
menteith
@menteith De acordo com seu código, ele chama getFile () e getAbsolutePath () em getFile (), mas getFile () retorna String e você não pode chamar getAbsolutePath () no objeto String
Almas Abdrazak
0

Com o Spring, você pode lê-lo facilmente da pasta de recursos (principal / recursos ou teste / recursos):

Por exemplo, crie um arquivo: 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;
}
MevlütÖzdemir
fonte
0
List<String> lines = Files.readAllLines(Paths.get("src/test/resources/foo.txt"));
lines.forEach(System.out::println);
zhuguowei
fonte