diff --git a/documentation/src/test/java/example/ParameterizedTestDemo.java b/documentation/src/test/java/example/ParameterizedTestDemo.java index 4a200726ebcd..6f806e54aaf6 100644 --- a/documentation/src/test/java/example/ParameterizedTestDemo.java +++ b/documentation/src/test/java/example/ParameterizedTestDemo.java @@ -174,7 +174,7 @@ void testWithEnumSourceRegex(ChronoUnit unit) { // tag::EnumSource_range_exclude_example[] @ParameterizedTest - @EnumSource(mode = EXCLUDE, from = "HOURS", to = "DAYS", names = { "HALF_DAYS" }) + @EnumSource(from = "HOURS", to = "DAYS", mode = EXCLUDE, names = { "HALF_DAYS" }) void testWithEnumSourceRangeExclude(ChronoUnit unit) { assertTrue(EnumSet.of(ChronoUnit.HOURS, ChronoUnit.DAYS).contains(unit)); assertFalse(EnumSet.of(ChronoUnit.HALF_DAYS).contains(unit)); diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/EnumArgumentsProvider.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/EnumArgumentsProvider.java index a68b43d5f371..606d02e19d64 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/EnumArgumentsProvider.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/EnumArgumentsProvider.java @@ -45,10 +45,16 @@ private > Set getEnumConstants(ExtensionContext c Class enumClass = determineEnumClass(context, enumSource); E[] constants = enumClass.getEnumConstants(); if (constants.length == 0) { + Preconditions.condition(enumSource.from().isEmpty() && enumSource.to().isEmpty(), + "No enum constant in " + enumClass.getSimpleName() + ", but 'from' or 'to' is not empty."); return EnumSet.noneOf(enumClass); } E from = enumSource.from().isEmpty() ? constants[0] : Enum.valueOf(enumClass, enumSource.from()); E to = enumSource.to().isEmpty() ? constants[constants.length - 1] : Enum.valueOf(enumClass, enumSource.to()); + Preconditions.condition(from.compareTo(to) <= 0, + () -> String.format( + "Invalid enum range: 'from' (%s) must come before 'to' (%s) in the natural order of enum constants.", + from, to)); return EnumSet.range(from, to); } diff --git a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/EnumSource.java b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/EnumSource.java index 673066b163b2..9c43c0ba465d 100644 --- a/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/EnumSource.java +++ b/junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/EnumSource.java @@ -99,7 +99,10 @@ * @see #names * @see #to * @see #mode + * + * @since 5.12 */ + @API(status = EXPERIMENTAL, since = "5.12") String from() default ""; /** @@ -112,12 +115,19 @@ * @see #names * @see #from * @see #mode + * + * @since 5.12 */ + @API(status = EXPERIMENTAL, since = "5.12") String to() default ""; /** * The enum constant selection mode. * + *

The mode only applies to the {@link #names} attribute and does not change + * the behavior of {@link #from} and {@link #to}, which always define a range + * based on the natural order of the enum constants. + * *

Defaults to {@link Mode#INCLUDE INCLUDE}. * * @see Mode#INCLUDE @@ -126,6 +136,8 @@ * @see Mode#MATCH_ANY * @see Mode#MATCH_NONE * @see #names + * @see #from + * @see #to */ Mode mode() default Mode.INCLUDE; diff --git a/jupiter-tests/src/test/java/org/junit/jupiter/params/provider/EnumArgumentsProviderTests.java b/jupiter-tests/src/test/java/org/junit/jupiter/params/provider/EnumArgumentsProviderTests.java index a3c405dcf23b..b7dc9e3cb5bf 100644 --- a/jupiter-tests/src/test/java/org/junit/jupiter/params/provider/EnumArgumentsProviderTests.java +++ b/jupiter-tests/src/test/java/org/junit/jupiter/params/provider/EnumArgumentsProviderTests.java @@ -164,6 +164,20 @@ void invalidEndingRangeIsDetected() { assertThat(exception).hasMessageContaining("No enum constant"); } + @Test + void invalidRangeOrderIsDetected() { + Exception exception = assertThrows(PreconditionViolationException.class, + () -> provideArguments(EnumWithFourConstants.class, "BAR", "FOO", Mode.INCLUDE).findAny()); + assertThat(exception).hasMessageContaining("Invalid enum range"); + } + + @Test + void invalidRangeIsDetectedWhenEnumWithNoConstantIsProvided() { + Exception exception = assertThrows(PreconditionViolationException.class, + () -> provideArguments(EnumWithNoConstant.class, "BAR", "FOO", Mode.INCLUDE).findAny()); + assertThat(exception).hasMessageContaining("No enum constant"); + } + static class TestCase { void methodWithCorrectParameter(EnumWithFourConstants parameter) { }