Sometimes tests require temporary directories for performing intermediate test steps. JUnit 5 provides the @TempDir
annotation that supplies a temporary directory to the test method or lifecycle methods. For temporary file support in JUnit 4, read this link.
@TempDir is an experimental feature. Check its latest status here.
1. @TempDir Annotation
Internally, @TempDir uses built-in TempDirectory
an extension that is a Junit Jupiter extension that creates and cleans up temporary directories.
1.1. Location of Temp Directory
Internally the JUnit uses Files.createTempDirectory() method for creating the temporary directory in the system.
Most likely, the createTempDirectory() method then makes use of the default system temporary file directory. The details of how the directory’s name is constructed are implementation-dependent and therefore not specified.
1.2. Creating a Temp Directory
The @TempDir annotation is used to create and cleanup the temporary directory created for a single test or a group of tests. We can only use @TempDir with the following types only: java.nio.file.Path
and java.io.File
. If we try to use @TempDir with a different type, then an org.junit.jupiter.api.extension.ParameterResolutionException will be thrown.
If the temporary directory cannot be created for some reason, an ExtensionConfigurationException will be thrown.
@TempDir
File tempDirectory;
//or
@TempDir
Path tempDirectory;
1.3. Using @TempDir in a Test Class
The @TempDir can be used via field injection (member fields) or parameter injection in a lifecycle or test method parameter. @TempDir is not supported on constructor parameters. A ParameterResolutionException will be thrown for a constructor parameter annotated with it.
//Static or Non-static member field
@TempDir
Path tempDir;
//or
//Test method argument
@Test
void tempDirectoryTestOne(@TempDir Path tempDir) throws IOException {}
1.4. Sharing a Temp Dir with Multiple Tests
All tests in a class will share the temporary directory when the annotation is present on a static
field or on a parameter of a @BeforeAll method.
@TempDir
static Path tempDir;
//or
@BeforeAll
static void setup(@TempDir Path tempDir) throws IOException
{
}
When @TempDir is only used on instance fields or on parameters in test, @BeforeEach, or @AfterEach methods — each test will use its own temporary directory.
@TempDir
Path tempDir;
//or
@BeforeEach
void setup(@TempDir Path tempDir) throws IOException
{
}
1.5. Deleting a Temp Directory
Before JUnit 5.9, when the test method or class has finished execution, JUnit will attempt to recursively delete all files and directories in the temporary directory and, finally, the temporary directory itself.
The test will fail with an IOException if there is any error in deleting any temporary file or directory.
Starting JUnit 5.9, it allows for specifying the cleanup policy via the CleanupMode
enum constants:
ALWAYS
: Always clean up a temporary directory after the test has been completed.DEFAULT
: Use the default cleanup mode.CleanupMode.ALWAYS
is the default cleanup policy.NEVER
: Never clean up a temporary directory after the test has been completed.- ON_SUCCESS: Only clean up a temporary directory if the test is completed successfully.
@TempDir(cleanup = CleanupMode.ON_SUCCESS)
2. @TempDir Examples
2.1. @TempDir as Test Method Argument
This approach is helpful when there is only a single test method where we need to take the help of a temporary file. We can directly pass the path to the temp file into the test method.
In the given test, we are writing some content to a file test.txt
in a temporary file. Then we read the same file again to match the content of the file with what we had written.
We are creating the text file as a temporary file which will get deleted after the test execution is complete.
Notice the tempDir
parameter to the test. It is of type java.nio.file.Path
and annotated with @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 as Instance Field
We can use this approach if we need to access the temporary file in more than one test method. When using an instance field, each test creates a new temporary file and deletes it after the test execution is complete.
For example, we are rewriting the first example. Both tests will create a new temporary file for them and delete it afterward.
@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 as Static Instance Field
This is not recommended but if we want to share the temporary file between multiple test methods.
@TempDir
static Path tempDir;
@Test
void tempDirectoryTestOne() throws IOException {
Path tempFile = tempDir.resolve("test.txt");
//create new temporary file
}
@Test
void tempDirectoryTestTwo() throws IOException {
Path tempFile = tempDir.resolve("test.txt");
//Reuses the same temporary file created by previous test
}
3. Best Practices
- If you want to copy some files into the temp directory before the test execution, you would typically do that in a @BeforeAll or @BeforeEach method in the test class.
@BeforeEach
void setup(@TempDir Path tempDir) throws IOException
{
Path tempFile = tempDir.resolve("test.txt");
Files.write(tempFile, Arrays.asList("some content"));
}
- Use static modifier with @TempDir annotated field if the same temporary file has to be shared between all the tests.
- In this case, use
@Order
annotation to enforce the test order and ensure the behavior is always consistent.
Happy Learning !!