JUnit 5 @TempDir – Temporary Directory Support

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 !!

Comments are closed for this article!

About Us

HowToDoInJava provides tutorials and how-to guides on Java and related technologies.

It also shares the best practices, algorithms & solutions and frequently asked interview questions.