Search code examples
javajunitjunit5

How to get rid of TemporaryFolder rule in Junit5


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?


Solution

  • You can use the @TempDir annotation (JUnit 5.4+), described in §2.22.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 type java.nio.file.Path or java.io.File with @TempDir or add a parameter of type java.nio.file.Path or java.io.File annotated with @TempDir to a lifecycle method or test method.

    Note on API status:

    API Status Since
    @TempDir Stable 5.10
    @TempDir#cleanup() Stable 5.11
    @TempDir#factory() Experimental 5.10

    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.11.4):

    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. An ExtensionConfigurationException or a ParameterResolutionException will be thrown in one of the following cases:

    • If the field type or parameter type is neither Path nor File.
    • If a field is declared as final.
    • If the temporary directory cannot be created.
    • If the field type or parameter type is File and a custom factory is used, which creates a temporary directory that does not belong to the default file system.

    In addition, a ParameterResolutionException 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 a static 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 to per_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 a static 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.

    Clean Up

    By default, when the end of the scope of a temporary directory is reached, — when the test method or class has finished execution — JUnit will attempt to clean up the temporary directory by recursively deleting 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.

    The cleanup() attribute allows you to configure the CleanupMode. If the cleanup mode is set to NEVER, the temporary directory will not be cleaned up after the test completes. If the cleanup mode is set to ON_SUCCESS, the temporary directory will only be cleaned up if the test completes successfully. By default, the ALWAYS clean up mode will be used, but this can be configured globally by setting the "junit.jupiter.tempdir.cleanup.mode.default" configuration parameter.