章
目
录
有时测试需要临时目录来执行中间测试步骤。JUnit 5提供了@TempDir注解,该注解为测试方法或生命周期方法提供临时目录。
1.@TempDir注解
内部,@TempDir使用内置的TempDirectory扩展,该扩展是Junit Jupiter扩展,用于创建和清理临时目录。
1.1 临时目录的位置
JUnit内部使用Files.createTempDirectory()方法来创建系统中的临时目录。
很可能,createTempDirectory()方法随后使用默认的系统临时文件目录。目录名称的构造细节是实现依赖的,因此没有指定。
1.2 创建临时目录
@TempDir注解用于为单个测试或一组测试创建和清理临时目录。我们只能将@TempDir用于以下类型:java.nio.file.Path和java.io.File。如果我们尝试将@TempDir用于不同的类型,则会抛出org.junit.jupiter.api.extension.ParameterResolutionException。
如果出于某种原因无法创建临时目录,则会抛出ExtensionConfigurationException。
@TempDir
File tempDirectory;
//或
@TempDir
Path tempDirectory;
1.3 在测试类中使用@TempDir
@TempDir可以通过字段注入(成员字段)或参数注入在生命周期或测试方法参数中使用。不支持在构造函数参数上使用@TempDir。如果对构造函数参数进行注解,则会抛出ParameterResolutionException。
//静态或非静态成员变量
@TempDir
Path tempDir;
//或
//测试方法参数
@Test
void tempDirectoryTestOne(@TempDir Path tempDir) throws IOException {}
1.4 与多个测试共享临时目录
当注解存在于静态字段上或者@BeforeAll方法的参数上时,一个类中的所有测试将共享同一个临时目录。
// 所有测试共享临时目录
@TempDir
static Path tempDir;
//或
@BeforeAll
static void setup(@TempDir Path tempDir) throws IOException
{
}
当@TempDir仅用于实例字段或在测试、@BeforeEach或@AfterEach方法的参数中时,每个测试将使用自己的临时目录。
//每个测试单独一个新的临时目录
@TempDir
Path tempDir;
//或
@BeforeEach
void setup(@TempDir Path tempDir) throws IOException
{
}
1.5.删除临时目录
在JUnit 5.9之前,当测试方法或类完成执行时,JUnit将尝试递归删除临时目录中的所有文件和目录,最后删除临时目录本身。
如果删除任何临时文件或目录时发生错误,测试将失败并抛出IOException。
从JUnit 5.9开始,允许通过CleanupMode枚举常量指定清理策略:
- ALWAYS:始终在测试完成后清理临时目录。
- DEFAULT:使用默认清理模式。默认情况下,CleanupMode.ALWAYS是默认清理策略。
- NEVER:从不清理测试完成后完成的临时目录。
- ON_SUCCESS:仅在测试成功完成后清理临时目录。
@TempDir(cleanup = CleanupMode.ON_SUCCESS)
2. @TempDir示例
2.1. @TempDir作为测试方法参数
当只有一个测试方法需要使用临时文件时,这种方法很有用。我们可以直接将临时文件的路径作为参数传递给测试方法。
在给定的测试中,我们将向名为test.txt的文件中写入一些内容,然后再次读取同一文件以匹配写入的内容。
我们创建了文本文件作为临时文件,该文件将在测试执行完成后被删除。
请注意,tempDir参数的类型为java.nio.file.Path,并被注解为@TempDir。
@Test
void tempDirectoryTestOne(@TempDir Path tempDir) throws IOException
{
Path tempFile = tempDir.resolve("test.txt");
List<String> lines = Arrays.asList("howtodoinjava.com");
Files.write(tempFile, Arrays.asList("howtodoinjava.com"));
Assertions.assertTrue(Files.exists(tempFile), "Temp File should have been created");
Assertions.assertEquals(Files.readAllLines(tempFile), lines);
}
2.2. 将@TempDir用作实例字段
如果我们需要在多个测试方法中访问临时文件,可以使用这种方法。使用实例字段时,每个测试都会创建一个新的临时文件,并在测试执行完成后将其删除。
例如,我们将重写第一个示例。两个测试将为他们创建新的临时文件,并在之后删除它。
@TempDir
Path tempDir;
@Test
void tempDirectoryTestOne() throws IOException {
Path tempFile = tempDir.resolve("test.txt");
List<String> lines = Arrays.asList("howtodoinjava.com");
Files.write(tempFile, Arrays.asList("howtodoinjava.com"));
Assertions.assertTrue(Files.exists(tempFile), "Temp File should have been created");
Assertions.assertEquals(Files.readAllLines(tempFile), lines);
}
@Test
void tempDirectoryTestTwo() throws IOException {
Path tempFile = tempDir.resolve("test2.txt");
//Test code
}
2.3 将@TempDir用作静态实例字段
虽然不推荐这样做,但如果我们想在多个测试方法之间共享临时文件。
@TempDir
static Path tempDir;
@Test
void tempDirectoryTestOne() throws IOException {
Path tempFile = tempDir.resolve("test.txt");
//创建新的临时文件
}
@Test
void tempDirectoryTestTwo() throws IOException {
Path tempFile = tempDir.resolve("test.txt");
//重复使用先前测试创建的相同临时文件
}
3.最佳实践
如果您想在测试执行之前将一些文件复制到临时目录中,通常可以在测试类中的@BeforeAll或@BeforeEach方法中这样做。
如果需要在所有测试之间共享相同的临时文件,请在@TempDir注解字段上使用静态修饰符。
@BeforeEach
void setup(@TempDir Path tempDir) throws IOException
{
Path tempFile = tempDir.resolve("test.txt");
Files.write(tempFile, Arrays.asList("some content"));
}
在这种情况下,使用@Order注解来强制执行测试顺序并确保行为始终一致。