Skip to content

Commit

Permalink
Fail fast when TempDirFactory::createTempDirectory returns null
Browse files Browse the repository at this point in the history
  • Loading branch information
scordio committed Jul 26, 2024
1 parent adf6d43 commit f8a4fa4
Show file tree
Hide file tree
Showing 4 changed files with 150 additions and 34 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,8 @@ repository on GitHub.
`assertInstanceOf` methods introduced in `5.8` version.
* New generators in `DynamicTest` that take a `Stream`/`Iterator` of `Named<Executable>`
along with a convenient `NamedExecutable` interface that can simplify writing dynamic
tests, in particular in recent version of Java that support records.
tests, in particular in recent versions of Java that support records.
* `@TempDir` now fails fast when `TempDirFactory::createTempDirectory` returns `null`


[[release-notes-5.11.0-RC1-junit-vintage]]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -286,7 +286,8 @@ static class CloseablePath implements CloseableResource {

CloseablePath(TempDirFactory factory, CleanupMode cleanupMode, AnnotatedElementContext elementContext,
ExtensionContext extensionContext) throws Exception {
this.dir = factory.createTempDirectory(elementContext, extensionContext);
this.dir = Preconditions.notNull(factory.createTempDirectory(elementContext, extensionContext),
"temp directory must not be null");
this.factory = factory;
this.cleanupMode = cleanupMode;
this.extensionContext = extensionContext;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,14 +54,15 @@
import org.junit.jupiter.api.extension.ParameterResolutionException;
import org.junit.jupiter.api.io.TempDir;
import org.junit.jupiter.api.io.TempDirFactory;
import org.junit.jupiter.api.io.TempDirFactory.Standard;
import org.junit.jupiter.engine.AbstractJupiterTestEngineTests;
import org.junit.platform.commons.PreconditionViolationException;
import org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder;
import org.junit.platform.testkit.engine.EngineExecutionResults;
import org.junit.platform.testkit.engine.Events;

/**
* Integration tests for the legacy behavior of the {@link TempDirectory}
* extension to create a single temp directory per context, i.e. test class or
* extension to create a single temp directory per context, i.e., test class or
* method.
*
* @since 5.4
Expand All @@ -74,6 +75,13 @@ protected EngineExecutionResults executeTestsForClass(Class<?> testClass) {
return executeTests(requestBuilder(testClass).build());
}

private EngineExecutionResults executeTestsForClassWithDefaultFactory(Class<?> testClass,
Class<? extends TempDirFactory> factoryClass) {
return executeTests(requestBuilder(testClass) //
.configurationParameter(TempDir.DEFAULT_FACTORY_PROPERTY_NAME, factoryClass.getName()) //
.build());
}

@SuppressWarnings("deprecation")
private static LauncherDiscoveryRequestBuilder requestBuilder(Class<?> testClass) {
return request() //
Expand Down Expand Up @@ -295,25 +303,20 @@ void resolvesSeparateTempDirWhenAnnotationIsUsedOnAfterAllMethodParameterOnly()
@TestMethodOrder(OrderAnnotation.class)
class DefaultFactory {

private Events executeTestsForClassWithDefaultFactory(Class<?> testClass,
Class<? extends TempDirFactory> factoryClass) {
return TempDirectoryPerContextTests.super.executeTests(requestBuilder(testClass) //
.configurationParameter(TempDir.DEFAULT_FACTORY_PROPERTY_NAME, factoryClass.getName()) //
.build()).testEvents();
}

@Test
@DisplayName("set to Jupiter's default")
void supportsStandardDefaultFactory() {
executeTestsForClassWithDefaultFactory(StandardDefaultFactoryTestCase.class, TempDirFactory.Standard.class) //
.assertStatistics(stats -> stats.started(1).succeeded(1));
var results = executeTestsForClassWithDefaultFactory(StandardDefaultFactoryTestCase.class, Standard.class);

results.testEvents().assertStatistics(stats -> stats.started(1).succeeded(1));
}

@Test
@DisplayName("set to custom factory")
void supportsCustomDefaultFactory() {
executeTestsForClassWithDefaultFactory(NonStandardDefaultFactoryTestCase.class, Factory.class) //
.assertStatistics(stats -> stats.started(1).succeeded(1));
var results = executeTestsForClassWithDefaultFactory(CustomDefaultFactoryTestCase.class, Factory.class);

results.testEvents().assertStatistics(stats -> stats.started(1).succeeded(1));
}

private static class Factory implements TempDirFactory {
Expand Down Expand Up @@ -359,8 +362,7 @@ void onlySupportsParametersOfTypePathAndFile() {
var results = executeTestsForClass(InvalidTestCase.class);

// @formatter:off
TempDirectoryPerContextTests.assertSingleFailedTest(results,
instanceOf(ParameterResolutionException.class),
assertSingleFailedTest(results, instanceOf(ParameterResolutionException.class),
message(m -> m.matches("Failed to resolve parameter \\[java.lang.String .+] in method \\[.+]: .+")),
cause(
instanceOf(ExtensionConfigurationException.class),
Expand Down Expand Up @@ -389,14 +391,13 @@ void doesNotSupportTempDirAnnotationOnConstructorParameterWithTestInstancePerCla
}

@Test
@DisplayName("when @TempDir factory is not Standard")
@DisplayName("when non-default @TempDir factory is set")
@Order(32)
void onlySupportsStandardTempDirFactory() {
var results = executeTestsForClass(NonStandardFactoryTestCase.class);
void doesNotSupportNonDefaultTempDirFactory() {
var results = executeTestsForClass(NonDefaultFactoryTestCase.class);

// @formatter:off
TempDirectoryPerContextTests.assertSingleFailedTest(results,
instanceOf(ParameterResolutionException.class),
assertSingleFailedTest(results, instanceOf(ParameterResolutionException.class),
message(m -> m.matches("Failed to resolve parameter \\[.+] in method \\[.+]: .+")),
cause(
instanceOf(ExtensionConfigurationException.class),
Expand All @@ -405,6 +406,35 @@ void onlySupportsStandardTempDirFactory() {
// @formatter:on
}

@Test
@DisplayName("when default @TempDir factory returns null")
@Order(33)
void doesNotSupportCustomDefaultTempDirFactoryReturningNull() {
var results = executeTestsForClassWithDefaultFactory(CustomDefaultFactoryReturningNullTestCase.class,
FactoryReturningNull.class);

// @formatter:off
assertSingleFailedTest(results, instanceOf(ParameterResolutionException.class),
message(m -> m.matches("Failed to resolve parameter \\[.+] in method \\[.+]: .+")),
cause(
instanceOf(ExtensionConfigurationException.class),
message("Failed to create default temp directory"),
cause(
instanceOf(PreconditionViolationException.class),
message("temp directory must not be null")
)
));
// @formatter:on
}

private static class FactoryReturningNull implements TempDirFactory {

@Override
public Path createTempDirectory(AnnotatedElementContext elementContext, ExtensionContext extensionContext) {
return null;
}
}

}

@Nested
Expand Down Expand Up @@ -685,7 +715,7 @@ static class AnnotationOnConstructorParameterWithTestInstancePerClassTestCase
}
}

static class NonStandardFactoryTestCase {
static class NonDefaultFactoryTestCase {

@Test
void test(@SuppressWarnings("unused") @TempDir(factory = Factory.class) Path tempDir) {
Expand All @@ -712,7 +742,7 @@ void test(@TempDir Path tempDir1, @TempDir Path tempDir2) {

}

static class NonStandardDefaultFactoryTestCase {
static class CustomDefaultFactoryTestCase {

@Test
void test(@TempDir Path tempDir1, @TempDir Path tempDir2) {
Expand All @@ -721,6 +751,15 @@ void test(@TempDir Path tempDir1, @TempDir Path tempDir2) {

}

static class CustomDefaultFactoryReturningNullTestCase {

@Test
void test(@SuppressWarnings("unused") @TempDir Path tempDir) {
// never called
}

}

static class AnnotationOnBeforeAllMethodParameterTestCase extends BaseSharedTempDirParameterInjectionTestCase {

@BeforeAll
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@
import org.junit.jupiter.engine.AbstractJupiterTestEngineTests;
import org.junit.jupiter.engine.Constants;
import org.junit.jupiter.engine.extension.TempDirectory.FileOperations;
import org.junit.platform.commons.PreconditionViolationException;
import org.junit.platform.engine.reporting.ReportEntry;
import org.junit.platform.testkit.engine.EngineExecutionResults;

Expand All @@ -95,6 +96,14 @@
@DisplayName("TempDirectory extension (per declaration)")
class TempDirectoryPerDeclarationTests extends AbstractJupiterTestEngineTests {

private EngineExecutionResults executeTestsForClassWithDefaultFactory(Class<?> testClass,
Class<? extends TempDirFactory> factoryClass) {
return executeTests(request() //
.selectors(selectClass(testClass)) //
.configurationParameter(TempDir.DEFAULT_FACTORY_PROPERTY_NAME, factoryClass.getName()) //
.build());
}

@BeforeEach
@AfterEach
void resetStaticVariables() {
Expand Down Expand Up @@ -272,8 +281,7 @@ void onlySupportsParametersOfTypePathAndFile() {
var results = executeTestsForClass(InvalidTestCase.class);

// @formatter:off
TempDirectoryPerDeclarationTests.assertSingleFailedTest(results,
instanceOf(ParameterResolutionException.class),
assertSingleFailedTest(results, instanceOf(ParameterResolutionException.class),
message(m -> m.matches("Failed to resolve parameter \\[java.lang.String .+] in method \\[.+]: .+")),
cause(
instanceOf(ExtensionConfigurationException.class),
Expand Down Expand Up @@ -301,6 +309,55 @@ void doesNotSupportTempDirAnnotationOnConstructorParameterWithTestInstancePerCla
"@TempDir is not supported on constructor parameters. Please use field injection instead.");
}

@Test
@DisplayName("when @TempDir factory returns null")
@Order(32)
void doesNotSupportTempDirFactoryReturningNull() {
var results = executeTestsForClass(FactoryReturningNullTestCase.class);

// @formatter:off
assertSingleFailedTest(results, instanceOf(ParameterResolutionException.class),
message(m -> m.matches("Failed to resolve parameter \\[.+] in method \\[.+]: .+")),
cause(
instanceOf(ExtensionConfigurationException.class),
message("Failed to create default temp directory"),
cause(
instanceOf(PreconditionViolationException.class),
message("temp directory must not be null")
)
));
// @formatter:on
}

@Test
@DisplayName("when default @TempDir factory returns null")
@Order(33)
void doesNotSupportCustomDefaultTempDirFactoryReturningNull() {
var results = executeTestsForClassWithDefaultFactory(CustomDefaultFactoryReturningNullTestCase.class,
FactoryReturningNull.class);

// @formatter:off
assertSingleFailedTest(results, instanceOf(ParameterResolutionException.class),
message(m -> m.matches("Failed to resolve parameter \\[.+] in method \\[.+]: .+")),
cause(
instanceOf(ExtensionConfigurationException.class),
message("Failed to create default temp directory"),
cause(
instanceOf(PreconditionViolationException.class),
message("temp directory must not be null")
)
));
// @formatter:on
}

private static class FactoryReturningNull implements TempDirFactory {

@Override
public Path createTempDirectory(AnnotatedElementContext elementContext, ExtensionContext extensionContext) {
return null;
}
}

}

@Nested
Expand Down Expand Up @@ -379,14 +436,6 @@ void supportsFactoryWithCustomMetaAnnotation() {
@TestMethodOrder(OrderAnnotation.class)
class DefaultFactory {

private EngineExecutionResults executeTestsForClassWithDefaultFactory(Class<?> testClass,
Class<? extends TempDirFactory> factoryClass) {
return TempDirectoryPerDeclarationTests.super.executeTests(request() //
.selectors(selectClass(testClass)) //
.configurationParameter(TempDir.DEFAULT_FACTORY_PROPERTY_NAME, factoryClass.getName()) //
.build());
}

@Test
@DisplayName("set to Jupiter's default")
void supportsStandardDefaultFactory() {
Expand Down Expand Up @@ -1369,6 +1418,23 @@ public Path createTempDirectory(AnnotatedElementContext elementContext, Extensio

}

static class FactoryReturningNullTestCase {

@Test
void test(@SuppressWarnings("unused") @TempDir(factory = Factory.class) Path tempDir) {
// never called
}

private static class Factory implements TempDirFactory {

@Override
public Path createTempDirectory(AnnotatedElementContext elementContext, ExtensionContext extensionContext) {
return null;
}
}

}

static class StandardDefaultFactoryTestCase {

@Test
Expand Down Expand Up @@ -1402,4 +1468,13 @@ void test(@TempDir Path tempDir1, @TempDir(factory = Standard.class) Path tempDi

}

static class CustomDefaultFactoryReturningNullTestCase {

@Test
void test(@SuppressWarnings("unused") @TempDir Path tempDir) {
// never called
}

}

}

0 comments on commit f8a4fa4

Please sign in to comment.