I’m migrating unit tests from Junit4 to Junit5. In the test I’m using TemporaryFolder
rule from Junit4 API. To keep the test working I added @EnableRuleMigrationSupport
annotation:
@EnableRuleMigrationSupport public final class SomeTest { @Rule public final TemporaryFolder tmp = new TemporaryFolder(); // tests ... }
As I understand, in Junit5 I need to use extensions instead of rules, but I can’t find any replacement for TemporaryFolder
in Junit5 extensions. Does it exist? How to correctly replace TemporaryFolder
rule with extension?
Advertisement
Answer
You can use the @TempDir
annotation (JUnit 5.4+), described in ยง2.20.1 of the JUnit 5 User Guide. From the user guide (emphasis mine):
The built-in
TempDirectory
extension is used to create and clean up a temporary directory for an individual test or all tests in a test class. It is registered by default. To use it, annotate a non-private field of typejava.nio.file.Path
orjava.io.File
with@TempDir
or add a parameter of typejava.nio.file.Path
orjava.io.File
annotated with@TempDir
to a lifecycle method or test method.
Note: This extension was added in version 5.4
and is currently (as of 5.8.2
) experimental.
Example of using an instance field:
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; import java.nio.file.Path; // or use java.io.File class SomeTests { @TempDir Path directory; // may be private since 5.8 }
โ Allow @TempDir fields to be private #2687
Example of using a parameter of a test method:
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; import java.nio.file.Path; // or use java.io.File class SomeTests { @Test void testFoo(@TempDir Path directory) { // do test... } }
Note: Constructor parameters are not supported.
When the directory is created and deleted is described in the Javadoc of @TempDir
(documentation quote from JUnit 5.8.2):
Creation
The temporary directory is only created if a field in a test class or a parameter in a lifecycle method or test method is annotated with
@TempDir
. If the field type or parameter type is neitherPath
norFile
or if the temporary directory cannot be created, anExtensionConfigurationException
or aParameterResolutionException
will be thrown as appropriate. In addition, aParameterResolutionException
will be thrown for a constructor parameter annotated with@TempDir
.Scope
By default, a separate temporary directory is created for every declaration of the
@TempDir
annotation. If you want to share a temporary directory across all tests in a test class, you should declare the annotation on astatic
field or on a parameter of a@BeforeAll
method.Old behavior
You can revert to the old behavior of using a single temporary directory by setting the
junit.jupiter.tempdir.scope
configuration parameter toper_context
. In that case, the scope of the temporary directory depends on where the first@TempDir
annotation is encountered when executing a test class. The temporary directory will be shared by all tests in a class when the annotation is present on astatic
field or on a parameter of a@BeforeAll
method. Otherwise โ for example, 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.Deletion
When the end of the scope of a temporary directory is reached, i.e. 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. In case deletion of a file or directory fails, an
IOException
will be thrown that will cause the test or test class to fail.