= Built-in Extensions

While the JUnit team encourages reusable extensions to be packaged and maintained in
separate libraries, JUnit Jupiter includes a few user-facing extension implementations
that are considered so generally useful that users shouldn't have to add another
dependency.

[[TempDirectory]]
== The @TempDir Extension

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-final, unassigned 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 test class constructor, lifecycle method, or
test method.

For example, the following test declares a parameter annotated with `@TempDir` for a
single test method, creates and writes to a file in the temporary directory, and checks
its content.

[source,java,indent=0]
.A test method that requires a temporary directory
----
include::example$java/example/TempDirectoryDemo.java[tags=user_guide_parameter_injection]
----

You can inject multiple temporary directories by specifying multiple annotated parameters.

[source,java,indent=0]
.A test method that requires multiple temporary directories
----
include::example$java/example/TempDirectoryDemo.java[tags=user_guide_multiple_directories]
----

WARNING: To revert to the old behavior of using a single temporary directory for the
entire test class or method (depending on which level the annotation is used), you can set
the `junit.jupiter.tempdir.scope` configuration parameter to `per_context`. However,
please note that this option is deprecated and will be removed in a future release.

The following example stores a _shared_ temporary directory in a `static` field. This
allows the same `sharedTempDir` to be used in all lifecycle methods and test methods of
the test class. For better isolation, you should use an instance field or constructor
injection so that each test method uses a separate directory.

[source,java,indent=0]
.A test class that shares a temporary directory across test methods
----
include::example$java/example/TempDirectoryDemo.java[tags=user_guide_field_injection]
----

The `@TempDir` annotation has an optional `cleanup` attribute that can be set to either
`NEVER`, `ON_SUCCESS`, or `ALWAYS`. If the cleanup mode is set to `NEVER`, the temporary
directory will not be deleted after the test completes. If it is set to `ON_SUCCESS`, the
temporary directory will only be deleted after the test if the test completed successfully.

The default cleanup mode is `ALWAYS`. You can use the
`junit.jupiter.tempdir.cleanup.mode.default`
xref:running-tests/configuration-parameters.adoc[configuration parameter] to override this default.

[source,java,indent=0]
.A test class with a temporary directory that doesn't get cleaned up
----
include::example$java/example/TempDirectoryDemo.java[tags=user_guide_cleanup_mode]
----

`@TempDir` supports the programmatic creation of temporary directories via the optional
`factory` attribute. This is typically used to gain control over the temporary directory
creation, like defining the parent directory or the file system that should be used.

Factories can be created by implementing `TempDirFactory`. Implementations must provide a
no-args constructor and should not make any assumptions regarding when and how many times
they are instantiated, but they can assume that their `createTempDirectory(...)` and
`close()` methods will both be called once per instance, in this order, and from the same
thread.

The default implementation available in Jupiter delegates directory creation to
`java.nio.file.Files::createTempDirectory` which uses the default file system and the
system's temporary directory as the parent directory. It passes `junit-` as the prefix
string of the generated directory name to help identify it as a created by JUnit.

The following example defines a factory that uses the test name as the directory name
prefix instead of the `junit` constant value.

[source,java,indent=0]
.A test class with a temporary directory having the test name as the directory name prefix
----
include::example$java/example/TempDirectoryDemo.java[tags=user_guide_factory_name_prefix]
----

It is also possible to use an in-memory file system like `{Jimfs}` for the creation of the
temporary directory. The following example demonstrates how to achieve that.

[source,java,indent=0]
.A test class with a temporary directory created with the Jimfs in-memory file system
----
include::example$java/example/TempDirectoryDemo.java[tags=user_guide_factory_jimfs]
----

`@TempDir` can also be used as a xref:writing-tests/annotations.adoc#annotations[meta-annotation] to
reduce repetition. The following code listing shows how to create a custom `@JimfsTempDir`
annotation that can be used as a drop-in replacement for
`@TempDir(factory = JimfsTempDirFactory.class)`.

[source,java,indent=0]
.A custom annotation meta-annotated with `@TempDir`
----
include::example$java/example/TempDirectoryDemo.java[tags=user_guide_composed_annotation]
----

The following example demonstrates how to use the custom `@JimfsTempDir` annotation.

[source,java,indent=0]
.A test class using the custom annotation
----
include::example$java/example/TempDirectoryDemo.java[tags=user_guide_composed_annotation_usage]
----

Meta-annotations or additional annotations on the field or parameter the `TempDir`
annotation is declared on might expose additional attributes to configure the factory.
Such annotations and related attributes can be accessed via the `AnnotatedElementContext`
parameter of the `createTempDirectory(...)` method.

You can use the `junit.jupiter.tempdir.factory.default` xref:running-tests/configuration-parameters.adoc[configuration parameter] to specify the fully qualified class name of the
`TempDirFactory` you would like to use by default. Just like for factories configured via
the `factory` attribute of the `@TempDir` annotation, the supplied class has to implement
the `TempDirFactory` interface. The default factory will be used for all `@TempDir`
annotations unless the `factory` attribute of the annotation specifies a different factory.

In summary, the factory for a temporary directory is determined according to the following
precedence rules:

1. The `factory` attribute of the `@TempDir` annotation, if present
2. The default `TempDirFactory` configured via the configuration
parameter, if present
3. Otherwise, `org.junit.jupiter.api.io.TempDirFactory$Standard` will be used.

[[AutoClose]]
== The @AutoClose Extension

The built-in `{AutoCloseExtension}` automatically closes resources associated with fields.
It is registered by default. To use it, annotate a field in a test class with
`{AutoClose}`.

`@AutoClose` fields may be either `static` or non-static. If the value of an `@AutoClose`
field is `null` when it is evaluated the field will be ignored, but a warning message will
be logged to inform you.

By default, `@AutoClose` expects the value of the annotated field to implement a `close()`
method that will be invoked to close the resource. However, developers can customize the
name of the close method via the `value` attribute. For example, `@AutoClose("shutdown")`
instructs JUnit to look for a `shutdown()` method to close the resource.

`@AutoClose` fields are inherited from superclasses. Furthermore, `@AutoClose` fields from
subclasses will be closed before `@AutoClose` fields in superclasses.

When multiple `@AutoClose` fields exist within a given test class, the order in which the
resources are closed depends on an algorithm that is deterministic but intentionally
nonobvious. This ensures that subsequent runs of a test suite close resources in the same
order, thereby allowing for repeatable builds.

The `AutoCloseExtension` implements the `AfterAllCallback` and
`TestInstancePreDestroyCallback` extension APIs. Consequently, a `static` `@AutoClose`
field will be closed after all tests in the current test class have completed, effectively
after `@AfterAll` methods have executed for the test class. A non-static `@AutoClose`
field will be closed before the current test class instance is destroyed. Specifically, if
the test class is configured with `@TestInstance(Lifecycle.PER_METHOD)` semantics, a
non-static `@AutoClose` field will be closed after the execution of each test method, test
factory method, or test template method. However, if the test class is configured with
`@TestInstance(Lifecycle.PER_CLASS)` semantics, a non-static `@AutoClose` field will not
be closed until the current test class instance is no longer needed, which means after
`@AfterAll` methods and after all `static` `@AutoClose` fields have been closed.

The following example demonstrates how to annotate an instance field with `@AutoClose` so
that the resource is automatically closed after test execution. In this example, we assume
that the default `@TestInstance(Lifecycle.PER_METHOD)` semantics apply.

[source,java,indent=0]
.A test class using `@AutoClose` to close a resource
----
include::example$java/example/AutoCloseDemo.java[tags=user_guide_example]
----
<1> Annotate an instance field with `@AutoClose`.
<2> `WebClient` implements `java.lang.AutoCloseable` which defines a `close()` method that
    will be invoked after each `@Test` method.
