JUnit 5测试中的临时目录(附实例及代码)

1,024 阅读2分钟

JUnit 4TemporaryFolder @Rule 允许开发人员利用临时目录来创建测试。在JUnit 5中,不支持@Rules,因此测试文件和目录需要一点额外的工作。幸运的是,在JUnit 5.4中,有一个新的内置扩展来处理测试中的临时目录,而且它非常容易使用:

@TempDir

@org.junit.jupiter.api.io.TempDir 注解可以用来注解类字段或生命周期中的参数(例如: )或测试方法的类型 或 。一旦这样做了,临时目录就会被创建。一旦测试方法或类执行完毕,该目录及其在测试执行过程中创建的内容将被删除。@BeforeEach File Path

要测试的代码

在这个简单的例子中,我们将测试FileWriter 类,它有一个单一的方法将文本内容写入一个新文件:


public class FileWriter {

    public void writeTo(String path, String content) throws IOException {
        Path target = Paths.get(path);
        if (Files.exists(target)) {
            throw new IOException("file already exists");
        }
        Files.copy(new ByteArrayInputStream(content.getBytes(StandardCharsets.UTF_8)), target);
    }
}

@TempDir 作为测试方法的参数

在这个例子中,我们将用@TempDir 注释来测试参数:

import org.junit.jupiter.api.io.TempDir;

@Test
void writesContentToFile(@TempDir Path tempDir) throws IOException {
    // arrange
    Path output = tempDir
            .resolve("output.txt");

    // act
    fileWriter.writeTo(output.toString(), "test");

    // assert
    assertAll(
            () -> assertTrue(Files.exists(output)),
            () -> assertLinesMatch(List.of("test"), Files.readAllLines(output))
    );
}

@TempDir 作为一个实例字段

import org.junit.jupiter.api.io.TempDir;

class FileWriterTest {

    private FileWriter fileWriter = new FileWriter();

    @TempDir
    Path tempDir;

    @BeforeEach
    void beforeEach() {
        assertTrue(Files.isDirectory(this.tempDir));
    }

    @RepeatedTest(3)
    void throwsErrorWhenTargetFileExists() throws IOException {
        // arrange
        Path output = Files.createFile(
                tempDir.resolve("output.txt")
        );

        // act & assert
        IOException expectedException = assertThrows(IOException.class, () -> fileWriter.writeTo(output.toString(), "test"));
        assertEquals("file already exists", expectedException.getMessage());
    }
}

基于上述例子,我们可以看到,每次重复测试都会使用一个新的临时目录(根据标准测试类的生命周期),因此方法的安排部分执行起来没有任何错误。

共享@TempDir

如果需要在测试方法之间共享一个临时目录,我们可以创建一个静态字段并重复使用临时目录,如下面的例子:

import org.junit.jupiter.api.io.TempDir;

class FileWriterTest {

    private FileWriter fileWriter = new FileWriter();

    @TempDir
    static Path tempDir;

    @BeforeAll
    static void setUp() {
        assertTrue(Files.isDirectory(tempDir));
    }

    @RepeatedTest(3)
    void throwsErrorWhenTargetFileExists(RepetitionInfo repetitionInfo) throws IOException {
        // arrange
        Path output = Files.createFile(
                tempDir.resolve(repetitionInfo.getCurrentRepetition() + "_output.txt")
        );

        // act & assert
        IOException expectedException = assertThrows(IOException.class, () -> fileWriter.writeTo(output.toString(), "test"));
        assertEquals("file already exists", expectedException.getMessage());
    }
}

请注意,测试方法的安排部分在每次执行时创建唯一的文件名(使用当前的重复计数器),否则FileAlreadyExistsException

总结

通过@TempDir ,你可以在测试中轻松地处理临时目录。这里没有魔法:你注解PathFile 对象,并在你需要时注入。其余的由JUnit为你处理。

在GitHub上找到这些例子:https://github.com/kolorobot/junit5-samples/tree/master/junit5-built-in-extensions

参见