JUnit 5 @TempDir – Temporary Directory Support

Sometimes tests require temporary directories for performing intermediate test steps. JUnit 5 provides the @TempDir annotation that can be used to supply a temporary directory to the test method or lifecycle methods.

Note

@TempDir is an experimental feature. Check its latest status here.

For temporary file support in Junit 4, read this link.

1. @TempDir and TempDirectory Extenstion

  • Internally, @TempDir uses TempDirectory extension that is a Junit Jupiter extension that creates and cleans up temporary directories.
  • @TempDir can be used via field injection (member fields) or parameter injection in a lifecycle method or test method (method parameters).
  • @TempDir is not supported on constructor parameters. A ParameterResolutionException will be thrown for a constructor parameter annotated with it.
  • @TempDir can be used to annotate a field in a test class or a parameter in a lifecycle method or test method.
  • We can only use @TempDir with the following types only:
    1. java.nio.file.Path
    2. 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.
  • The temporary directory will be shared by all tests in a class when the annotation is present on a static field or on a parameter of a @BeforeAll method.
  • 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.
  • 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.

Location of Temporary Files

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 as to how the name of the directory is constructed are implementation-dependent and therefore not specified.

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 pass the path to the temp file directly 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

If we need to access the temporary file in more than one test method then we can use this approach. 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
}

Note

The temp directory gets deleted after the current “scope”. The scope depends on where you declare @TempDir annotation.

2.3. @TempDir as Static 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 order of the tests and make sure the behavior is always consistent.

Happy Learning !!

Was this post helpful?

Join 7000+ Fellow Programmers

Subscribe to get new post notifications, industry updates, best practices, and much more. Directly into your inbox, for free.

Leave a Comment

HowToDoInJava

A blog about Java and its related technologies, the best practices, algorithms, interview questions, scripting languages, and Python.