Suporte ao diretório temporário do JUnit 5

Suporte ao diretório temporário do JUnit 5

1. Visão geral

Ao testar, geralmente precisamos acessar um arquivo temporário. No entanto, gerenciar a criação e a exclusão desses arquivos pode ser complicado.

Neste tutorial rápido,we’ll take a look at how JUnit 5 alleviates this by providing the TempDirectory extension.

Para obter um guia detalhado de testes com JUnit, verifique nosso excelenteGuide to JUnit 5.

2. A extensão TempDirectory

A partir da versão 5.4.2, o JUnit 5 fornece a extensão TempDirectory. No entanto, é importante observar que oficialmente esse ainda é um recursoexperimental e que somos incentivados a dar feedback à equipe JUnit.

Como veremos mais tarde,we can use this extension to create and clean up a temporary directory for an individual test or all tests in a test class.

Normalmente quandousing an extension, precisamos registrá-lo de dentro de um teste JUnit 5 usando a anotação@ExtendWith. Mas isso não é necessário com a extensão TempDirectory, que é incorporada e registrada por padrão.

3. Dependências do Maven

Primeiro, vamos adicionar as dependências do projeto que precisaremos para nossos exemplos.

Além da biblioteca JUnit 5 principaljunit-jupiter-engine, também precisaremos da bibliotecajunit-jupiter-api:


    org.junit.jupiter
    junit-jupiter-api
    5.4.2
    test

Como sempre, podemos obter a versão mais recente deMaven Central.

Além disso, também precisaremos adicionar a dependênciajunit-jupiter-params:


    org.junit.jupiter
    junit-jupiter-params
    5.4.2
    test

Novamente, podemos encontrar a versão mais recente emMaven Central.

4. Usando a anotação@TempDir

Para usar a extensão TempDirectory,we need to make use of the @TempDir annotation. Só podemos usar esta anotação com os dois tipos a seguir:

  • java.nio.file.Path

  • java.io.File

Na verdade, se tentarmos usá-lo com um tipo diferente, umorg.junit.jupiter.api.extension.ParameterResolutionException será lançado.

A seguir, vamos explorar várias maneiras diferentes de usar essa anotação.

4.1. @TempDir como um parâmetro de método

Vamos começar vendo comoinject a parameter annotated with @TempDir into a single test method:

@Test
void givenTestMethodWithTempDirectory_whenWriteToFile_thenContentIsCorrect(@TempDir Path tempDir)
  throws IOException {
    Path numbers = tempDir.resolve("numbers.txt");

    List lines = Arrays.asList("1", "2", "3");
    Files.write(numbers, lines);

    assertAll(
      () -> assertTrue("File should exist", Files.exists(numbers)),
      () -> assertLinesMatch(lines, Files.readAllLines(numbers)));
}

Como podemos ver, nosso método de teste cria e grava um arquivo chamadonumbers.txt no diretório temporáriotempDir.

Em seguida, verificamos se o arquivo existe e se o conteúdo corresponde ao que foi originalmente escrito. Muito bom e simples!

4.2. @TempDir em um campo de instância

Neste próximo exemplo, vamos anotar um campo em nossa classe de teste usando a anotação@TempDir:

@TempDir
File anotherTempDir;

@Test
void givenFieldWithTempDirectoryFile_whenWriteToFile_thenContentIsCorrect() throws IOException {
    assertTrue("Should be a directory ", this.anotherTempDir.isDirectory());

    File letters = new File(anotherTempDir, "letters.txt");
    List lines = Arrays.asList("x", "y", "z");

    Files.write(letters.toPath(), lines);

    assertAll(
      () -> assertTrue("File should exist", Files.exists(letters.toPath())),
      () -> assertLinesMatch(lines, Files.readAllLines(letters.toPath())));
}

Desta vez, usamos umjava.io.File para nosso diretório temporário. Novamente, escrevemos algumas linhas e verificamos que foram escritas com sucesso.

If we were to then use this single reference again in other test methods, each test would use its own temporary directory.

4.3. Um diretório temporário compartilhado

Às vezes, podemos querershare a temporary directory between test methods.

Podemos fazer isso declarando nosso campostatic:

@TempDir
static Path sharedTempDir;

@Test
@Order(1)
void givenFieldWithSharedTempDirectoryPath_whenWriteToFile_thenContentIsCorrect() throws IOException {
    Path numbers = sharedTempDir.resolve("numbers.txt");

    List lines = Arrays.asList("1", "2", "3");
    Files.write(numbers, lines);

    assertAll(
        () -> assertTrue("File should exist", Files.exists(numbers)),
        () -> assertLinesMatch(lines, Files.readAllLines(numbers)));
}

@Test
@Order(2)
void givenAlreadyWrittenToSharedFile_whenCheckContents_thenContentIsCorrect() throws IOException {
    Path numbers = sharedTempDir.resolve("numbers.txt");

    assertLinesMatch(Arrays.asList("1", "2", "3"), Files.readAllLines(numbers));
  }

The key point here is that we use a static field sharedTempDir which we share between the two test methods.

No primeiro teste, gravamos novamente algumas linhas em um arquivo chamadonumbers.txt. Depois, verificamos se o arquivo e o conteúdo já existem no próximo teste.

Também impomosthe order of the tests por meio da anotação@Order para garantir que o comportamento seja sempre consistente.

5. Pegadinhas

Agora, vamos revisar algumas das sutilezas que devemos conhecer ao trabalhar com a extensão TempDirectory.

5.1. Criação

O leitor curioso por aí provavelmente estará se perguntando onde esses arquivos temporários são realmente criados?

Bem, internamente a classe JUnitTemporaryDirectory faz uso do métodoFiles.createTempDirectory(String prefix). Likewise, this method then makes use of the default system temporary file directory.

Isso normalmente é especificado na variável de ambienteTMPDIR:

TMPDIR=/var/folders/3b/rp7016xn6fz9g0yf5_nj71m00000gn/T/

Por exemplo, resultando em um local de arquivo temporário:

/var/folders/3b/rp7016xn6fz9g0yf5_nj71m00000gn/T/junit5416670701666180307/numbers.txt

Enquanto isso, se o diretório temporário não puder ser criado, umExtensionConfigurationException será lançado conforme apropriado. Ou, como mencionado anteriormente, aParameterResolutionException.

5.2. Eliminação

Quando o método ou classe de teste terminar a execução e o diretório temporário sair do escopo,the JUnit framework will attempt to recursively delete all files and directories in that directory and, finally, the temporary directory itself.

Se houver um problema durante esta fase de exclusão, umIOException será lançado e o teste ou classe de teste falhará.

6. Conclusão

Para resumir, neste tutorial, exploramos a Extensão TempDirectory fornecida pela JUnit 5.

Primeiro, começamos introduzindo a extensão e aprendemos quais dependências do Maven precisamos para usá-la. A seguir, vimos vários exemplos de como usar a extensão em nossos testes de unidade.

Por fim, analisamos várias dicas, incluindo onde os arquivos temporários são criados e o que acontece durante a exclusão.

Como sempre, o código-fonte completo do artigo está disponívelover on GitHub.