Skip to content

Commit

Permalink
Support File parameters in TempDirectory extension
Browse files Browse the repository at this point in the history
Resolves: #1725
  • Loading branch information
rmannibucau authored and sbrannen committed Jan 16, 2019
1 parent 19acbfc commit e8140c0
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 13 deletions.
Expand Up @@ -70,7 +70,9 @@ repository on GitHub.
defining result-based callbacks invoked after text execution.
- See <<../user-guide/index.adoc#extensions-test-result-processing, Test Result
Processing>> in the User Guide for details.

* `TempDirectory` extension now also accepts to inject a parameter of type `File`.
- See <<../user-guide/index.adoc#writing-tests-built-in-extensions-TempDirectory,
The TempDirectory Extension>> in the User Guide for details.

[[release-notes-5.4.0-RC1-junit-vintage]]
=== JUnit Vintage
Expand Down
7 changes: 5 additions & 2 deletions documentation/src/docs/asciidoc/user-guide/writing-tests.adoc
Expand Up @@ -1656,8 +1656,8 @@ another dependency.

The `TempDirectory` extension can be used to create and clean up a temporary directory
for an individual test or all tests in a test class. To use it, register the extension
and add a parameter of type `java.nio.file.Path` annotated with `@TempDir` to your test
method, lifecycle method, or test class constructor.
and add a parameter of type `java.nio.file.Path` or `java.io.File` annotated with `@TempDir`
to your test method, lifecycle method, or test class constructor.

For example, the following test registers the extension for a single test method, creates
and writes to a file in the temporary directory, and checks its content.
Expand All @@ -1681,3 +1681,6 @@ of a custom parent directory of type `Path`. The following example uses the Jimf
----
include::{testDir}/example/TempDirectoryWithCustomFileSystemDemo.java[tags=user_guide]
----

WARNING: if you don't use a `FileSystem` relying on the default file system then `File` support
is not guaranteed.
Expand Up @@ -14,6 +14,7 @@
import static java.util.stream.Collectors.joining;
import static org.apiguardian.api.API.Status.EXPERIMENTAL;

import java.io.File;
import java.io.IOException;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
Expand Down Expand Up @@ -45,7 +46,8 @@
*
* <p>The temporary directory is only created if a test or lifecycle method or
* test class constructor has a parameter annotated with
* {@link TempDir @TempDir}. If the parameter type is not {@link Path} or if the
* {@link TempDir @TempDir}. If the parameter type is
* neither {@link Path} nor {@link File} or if the
* temporary directory could not be created, this extension will throw a
* {@link ParameterResolutionException}.
*
Expand Down Expand Up @@ -87,8 +89,8 @@ public final class TempDirectory implements ParameterResolver {

/**
* {@code TempDir} can be used to annotate a test or lifecycle method or
* test class constructor parameter of type {@link Path} that should be
* resolved into a temporary directory.
* test class constructor parameter of type {@link Path} or {@link File}
* that should be resolved into a temporary directory.
*
* @see TempDirectory
*/
Expand Down Expand Up @@ -225,15 +227,26 @@ public boolean supportsParameter(ParameterContext parameterContext, ExtensionCon
@Override
public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) {
Class<?> parameterType = parameterContext.getParameter().getType();
if (parameterType != Path.class) {
throw new ParameterResolutionException(
"Can only resolve parameter of type " + Path.class.getName() + " but was: " + parameterType.getName());
boolean expectsPath = parameterType == Path.class;
if (!expectsPath && parameterType != File.class) {
throw new ParameterResolutionException("Can only resolve parameter of type " + Path.class.getName() + " or "
+ File.class.getName() + " but was: " + parameterType.getName());
}
return extensionContext.getStore(NAMESPACE) //
Path path = extensionContext.getStore(NAMESPACE) //
.getOrComputeIfAbsent(KEY,
key -> tempDirProvider.get(parameterContext, extensionContext, TEMP_DIR_PREFIX),
CloseablePath.class) //
.get();
if (expectsPath) {
return path;
}
try {
return path.toFile();
}
catch (UnsupportedOperationException uoe) { // not default filesystem
throw new ParameterResolutionException("Unsupported FileSystem in tempDirProvider: " + tempDirProvider,
uoe);
}
}

private static CloseablePath createDefaultTempDir(String dirPrefix) {
Expand Down
Expand Up @@ -11,6 +11,7 @@
package org.junit.jupiter.api.support.io;

import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertSame;
Expand Down Expand Up @@ -161,13 +162,22 @@ void resolvesTempDirWithCustomParentDirFromProvider() {
@DisplayName("reports failure")
class Failures {

@Test
@DisplayName("when @TempDir is used on parameter of File type with a custom FileSystem")
void onlySupportsParametersOfTypeFileForDefaultFileSystem() {
var results = executeTests(selectClass(InvalidFileInjection.class));

assertSingleFailedTest(results, ParameterResolutionException.class,
"Unsupported FileSystem in tempDirProvider: org.junit.jupiter.api.support.io.TempDirectory"/*lambda*/);
}

@Test
@DisplayName("when @TempDir is used on parameter of wrong type")
void onlySupportsParametersOfTypePath() {
void onlySupportsParametersOfTypePathAndFile() {
var results = executeTests(selectClass(InvalidTestCase.class));

assertSingleFailedTest(results, ParameterResolutionException.class,
"Can only resolve parameter of type java.nio.file.Path");
"Can only resolve parameter of type java.nio.file.Path or java.io.File");
}

@Test
Expand Down Expand Up @@ -352,7 +362,46 @@ static class SeparateTempDirsWhenUsedOnForEachLifecycleMethodsWithTestInstancePe
@ExtendWith(TempDirectory.class)
static class InvalidTestCase {
@Test
void wrongParameterType(@SuppressWarnings("unused") @TempDir File ignored) {
void wrongParameterType(@SuppressWarnings("unused") @TempDir String ignored) {
fail("this should never be called");
}
}

@Nested
@DisplayName("User can rely on java.io.File injection type")
@ExtendWith(TempDirectory.class)
class FileInjection {
@Test
@DisplayName("File and Path injections lead to the same folder/behavior")
void checkFile(@TempDir File tempDir, @TempDir Path ref) {
Path path = tempDir.toPath();
assertEquals(ref.toAbsolutePath(), path.toAbsolutePath());
assertTrue(Files.exists(path));
}
}

@DisplayName("User can't rely on java.io.File injection type for custom filesystems")
static class InvalidFileInjection {
private FileSystem fileSystem;

@BeforeEach
void createFileSystem() {
fileSystem = Jimfs.newFileSystem();
}

@AfterEach
void closeFileSystem() throws Exception {
fileSystem.close();
}

@RegisterExtension
@SuppressWarnings("unused")
Extension tempDirectory = TempDirectory.createInCustomDirectory(
() -> Files.createDirectories(fileSystem.getPath("tmp")));

@Test
@DisplayName("File can't be injected using Jimfs FileSystem")
void failingInjection(@TempDir File tempDir) {
fail("this should never be called");
}
}
Expand Down

0 comments on commit e8140c0

Please sign in to comment.