diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedTestExtension.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedTestExtension.java index 8aed7644f2d8..023dd6fea6d2 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedTestExtension.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/ParameterizedTestExtension.java @@ -14,6 +14,7 @@ import static org.junit.platform.commons.support.AnnotationSupport.findRepeatableAnnotations; import java.lang.reflect.Method; +import java.util.List; import java.util.Optional; import java.util.concurrent.atomic.AtomicLong; import java.util.stream.Stream; @@ -74,8 +75,13 @@ public Stream provideTestTemplateInvocationContex ParameterizedTestNameFormatter formatter = createNameFormatter(extensionContext, methodContext); AtomicLong invocationCount = new AtomicLong(0); + List argumentsSources = findRepeatableAnnotations(methodContext.method, ArgumentsSource.class); + + Preconditions.notEmpty(argumentsSources, + "Configuration error: You must configure at least one arguments source for this @ParameterizedTest"); + // @formatter:off - return findRepeatableAnnotations(methodContext.method, ArgumentsSource.class) + return argumentsSources .stream() .map(ArgumentsSource::value) .map(clazz -> ParameterizedTestSpiInstantiator.instantiate(ArgumentsProvider.class, clazz, extensionContext)) diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/params/ParameterizedTestExtensionTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/params/ParameterizedTestExtensionTests.java index 638cdbf95e1f..fbdf70e080c7 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/params/ParameterizedTestExtensionTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/params/ParameterizedTestExtensionTests.java @@ -146,16 +146,23 @@ void throwsExceptionWhenParameterizedTestIsNotInvokedAtLeastOnce() { @Test void doesNotThrowExceptionWhenParametrizedTestDoesNotRequireArguments() { - var extensionContextWithAnnotatedTestMethod = getExtensionContextReturningSingleMethod( - new TestCaseAllowNoArgumentsMethod()); + var extensionContext = getExtensionContextReturningSingleMethod(new TestCaseAllowNoArgumentsMethod()); - var stream = this.parameterizedTestExtension.provideTestTemplateInvocationContexts( - extensionContextWithAnnotatedTestMethod); + var stream = this.parameterizedTestExtension.provideTestTemplateInvocationContexts(extensionContext); // cause the stream to be evaluated stream.toArray(); stream.close(); } + @Test + void throwsExceptionWhenParameterizedTestHasNoArgumentsSource() { + var extensionContext = getExtensionContextReturningSingleMethod(new TestCaseWithNoArgumentsSource()); + + assertThrows(PreconditionViolationException.class, + () -> this.parameterizedTestExtension.provideTestTemplateInvocationContexts(extensionContext), + "Configuration error: You must configure at least one arguments source for this @ParameterizedTest"); + } + @Test void throwsExceptionWhenArgumentsProviderIsNotStatic() { var extensionContextWithAnnotatedTestMethod = getExtensionContextReturningSingleMethod( @@ -323,8 +330,8 @@ void method() { static class TestCaseWithAnnotatedMethod { - @SuppressWarnings("JUnitMalformedDeclaration") @ParameterizedTest + @ArgumentsSource(ZeroArgumentsProvider.class) void method() { } } @@ -332,10 +339,27 @@ void method() { static class TestCaseAllowNoArgumentsMethod { @ParameterizedTest(allowZeroInvocations = true) + @ArgumentsSource(ZeroArgumentsProvider.class) void method() { } } + static class TestCaseWithNoArgumentsSource { + + @ParameterizedTest(allowZeroInvocations = true) + @SuppressWarnings("JUnitMalformedDeclaration") + void method() { + } + } + + static class ZeroArgumentsProvider implements ArgumentsProvider { + + @Override + public Stream provideArguments(ExtensionContext context) { + return Stream.empty(); + } + } + static class ArgumentsProviderWithCloseHandlerTestCase { @ParameterizedTest diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/params/ParameterizedTestIntegrationTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/params/ParameterizedTestIntegrationTests.java index 13739ea4e018..ad28cd7fa555 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/params/ParameterizedTestIntegrationTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/params/ParameterizedTestIntegrationTests.java @@ -457,7 +457,7 @@ void failsWhenArgumentsRequiredButNoneProvided() { } @Test - void failsWhenArgumentsAreNotRequiredAndNoneProvided() { + void doesNotFailWhenArgumentsAreNotRequiredAndNoneProvided() { var result = execute(ZeroArgumentsTestCase.class, "testThatDoesNotRequireArguments", String.class); result.allEvents().assertEventsMatchExactly( // event(engine(), started()), event(container(ZeroArgumentsTestCase.class), started()), @@ -467,6 +467,15 @@ void failsWhenArgumentsAreNotRequiredAndNoneProvided() { event(engine(), finishedSuccessfully())); } + @Test + void failsWhenNoArgumentsSourceIsDeclared() { + var result = execute(ZeroArgumentsTestCase.class, "testThatHasNoArgumentsSource", String.class); + result.containerEvents().assertThatEvents() // + .haveExactly(1, // + event(displayName("testThatHasNoArgumentsSource(String)"), finishedWithFailure(message( + "Configuration error: You must configure at least one arguments source for this @ParameterizedTest")))); + } + private EngineExecutionResults execute(DiscoverySelector... selectors) { return EngineTestKit.engine(new JupiterTestEngine()).selectors(selectors).execute(); } @@ -2428,6 +2437,12 @@ void testThatDoesNotRequireArguments(String argument) { fail("This test should not be executed, because no arguments are provided."); } + @ParameterizedTest(allowZeroInvocations = true) + @SuppressWarnings("JUnitMalformedDeclaration") + void testThatHasNoArgumentsSource(String argument) { + fail("This test should not be executed, because no arguments source is declared."); + } + public static Stream zeroArgumentsProvider() { return Stream.empty(); }