JUnit 5 @TempDir 注解详解

后端 潘老师 7个月前 (10-24) 125 ℃ (0) 扫码查看

有时测试需要临时目录来执行中间测试步骤。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注解来强制执行测试顺序并确保行为始终一致。


版权声明:本站文章,如无说明,均为本站原创,转载请注明文章来源。如有侵权,请联系博主删除。
本文链接:https://www.panziye.com/back/10292.html
喜欢 (0)
请潘老师喝杯Coffee吧!】
分享 (0)
用户头像
发表我的评论
取消评论
表情 贴图 签到 代码

Hi,您需要填写昵称和邮箱!

  • 昵称【必填】
  • 邮箱【必填】
  • 网址【可选】