Skip to content

Commit 57dfcb5

Browse files
committed
Allow repeating @…Source annotations when used as meta annotations
Fixes #4063. (cherry picked from commit 4ff42a7)
1 parent 09cd8b3 commit 57dfcb5

File tree

10 files changed

+125
-34
lines changed

10 files changed

+125
-34
lines changed

documentation/src/docs/asciidoc/release-notes/release-notes-5.11.3.adoc

+2
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ on GitHub.
3737

3838
* Extensions can once again be registered via multiple `@ExtendWith` meta-annotations on
3939
the same composed annotation on a field within a test class.
40+
* All `@...Source` annotations of parameterized tests can now also be repeated when used
41+
as meta annotations.
4042

4143

4244
[[release-notes-5.11.3-junit-jupiter-deprecations-and-breaking-changes]]

junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/ArgumentsSources.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
* @since 5.0
3232
* @see org.junit.jupiter.params.provider.ArgumentsSource
3333
*/
34-
@Target(ElementType.METHOD)
34+
@Target({ ElementType.ANNOTATION_TYPE, ElementType.METHOD })
3535
@Retention(RetentionPolicy.RUNTIME)
3636
@Documented
3737
@API(status = STABLE, since = "5.7")

junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/CsvFileSources.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
* @see CsvFileSource
3333
* @see java.lang.annotation.Repeatable
3434
*/
35-
@Target(ElementType.METHOD)
35+
@Target({ ElementType.ANNOTATION_TYPE, ElementType.METHOD })
3636
@Retention(RetentionPolicy.RUNTIME)
3737
@Documented
3838
@API(status = STABLE, since = "5.11")

junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/CsvSources.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
* @see CsvSource
3333
* @see java.lang.annotation.Repeatable
3434
*/
35-
@Target(ElementType.METHOD)
35+
@Target({ ElementType.ANNOTATION_TYPE, ElementType.METHOD })
3636
@Retention(RetentionPolicy.RUNTIME)
3737
@Documented
3838
@API(status = STABLE, since = "5.11")

junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/EnumSources.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
* @see EnumSource
3333
* @see java.lang.annotation.Repeatable
3434
*/
35-
@Target(ElementType.METHOD)
35+
@Target({ ElementType.ANNOTATION_TYPE, ElementType.METHOD })
3636
@Retention(RetentionPolicy.RUNTIME)
3737
@Documented
3838
@API(status = STABLE, since = "5.11")

junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/FieldSources.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
* @see FieldSource
3333
* @see java.lang.annotation.Repeatable
3434
*/
35-
@Target(ElementType.METHOD)
35+
@Target({ ElementType.ANNOTATION_TYPE, ElementType.METHOD })
3636
@Retention(RetentionPolicy.RUNTIME)
3737
@Documented
3838
@API(status = EXPERIMENTAL, since = "5.11")

junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/MethodSources.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
* @see MethodSource
3333
* @see java.lang.annotation.Repeatable
3434
*/
35-
@Target(ElementType.METHOD)
35+
@Target({ ElementType.ANNOTATION_TYPE, ElementType.METHOD })
3636
@Retention(RetentionPolicy.RUNTIME)
3737
@Documented
3838
@API(status = STABLE, since = "5.11")

junit-jupiter-params/src/main/java/org/junit/jupiter/params/provider/ValueSources.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
* @see ValueSource
3333
* @see java.lang.annotation.Repeatable
3434
*/
35-
@Target(ElementType.METHOD)
35+
@Target({ ElementType.ANNOTATION_TYPE, ElementType.METHOD })
3636
@Retention(RetentionPolicy.RUNTIME)
3737
@Documented
3838
@API(status = STABLE, since = "5.11")

jupiter-tests/src/test/java/org/junit/jupiter/params/ParameterizedTestIntegrationTests.java

+116-24
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111
package org.junit.jupiter.params;
1212

13+
import static java.lang.annotation.RetentionPolicy.RUNTIME;
1314
import static org.assertj.core.api.Assertions.assertThat;
1415
import static org.assertj.core.api.Assertions.within;
1516
import static org.junit.jupiter.api.Assertions.assertEquals;
@@ -40,7 +41,6 @@
4041

4142
import java.lang.annotation.ElementType;
4243
import java.lang.annotation.Retention;
43-
import java.lang.annotation.RetentionPolicy;
4444
import java.lang.annotation.Target;
4545
import java.util.ArrayList;
4646
import java.util.Arrays;
@@ -1093,65 +1093,73 @@ private EngineExecutionResults execute(String methodName, Class<?>... methodPara
10931093
@Nested
10941094
class RepeatableSourcesIntegrationTests {
10951095

1096-
@Test
1097-
void executesWithRepeatableCsvFileSource() {
1098-
var results = execute("testWithRepeatableCsvFileSource", String.class, String.class);
1096+
@ParameterizedTest
1097+
@ValueSource(strings = { "testWithRepeatableCsvFileSource", "testWithRepeatableCsvFileSourceAsMetaAnnotation" })
1098+
void executesWithRepeatableCsvFileSource(String methodName) {
1099+
var results = execute(methodName, String.class, String.class);
10991100
results.allEvents().assertThatEvents() //
11001101
.haveExactly(1,
11011102
event(test(), displayName("[1] column1=foo, column2=1"), finishedWithFailure(message("foo 1")))) //
11021103
.haveExactly(1, event(test(), displayName("[5] column1=FRUIT = apple, column2=RANK = 1"),
11031104
finishedWithFailure(message("apple 1"))));
11041105
}
11051106

1106-
@Test
1107-
void executesWithRepeatableCsvSource() {
1108-
var results = execute("testWithRepeatableCsvSource", String.class);
1107+
@ParameterizedTest
1108+
@ValueSource(strings = { "testWithRepeatableCsvSource", "testWithRepeatableCsvSourceAsMetaAnnotation" })
1109+
void executesWithRepeatableCsvSource(String methodName) {
1110+
var results = execute(methodName, String.class);
11091111
results.allEvents().assertThatEvents() //
11101112
.haveExactly(1, event(test(), displayName("[1] argument=a"), finishedWithFailure(message("a")))) //
11111113
.haveExactly(1, event(test(), displayName("[2] argument=b"), finishedWithFailure(message("b"))));
11121114
}
11131115

1114-
@Test
1115-
void executesWithRepeatableMethodSource() {
1116-
var results = execute("testWithRepeatableMethodSource", String.class);
1116+
@ParameterizedTest
1117+
@ValueSource(strings = { "testWithRepeatableMethodSource", "testWithRepeatableMethodSourceAsMetaAnnotation" })
1118+
void executesWithRepeatableMethodSource(String methodName) {
1119+
var results = execute(methodName, String.class);
11171120
results.allEvents().assertThatEvents() //
11181121
.haveExactly(1,
11191122
event(test(), displayName("[1] argument=some"), finishedWithFailure(message("some")))) //
11201123
.haveExactly(1,
11211124
event(test(), displayName("[2] argument=other"), finishedWithFailure(message("other"))));
11221125
}
11231126

1124-
@Test
1125-
void executesWithRepeatableEnumSource() {
1126-
var results = execute("testWithRepeatableEnumSource", Action.class);
1127+
@ParameterizedTest
1128+
@ValueSource(strings = { "testWithRepeatableEnumSource", "testWithRepeatableEnumSourceAsMetaAnnotation" })
1129+
void executesWithRepeatableEnumSource(String methodName) {
1130+
var results = execute(methodName, Action.class);
11271131
results.allEvents().assertThatEvents() //
11281132
.haveExactly(1, event(test(), displayName("[1] argument=FOO"), finishedWithFailure(message("FOO")))) //
11291133
.haveExactly(1,
11301134
event(test(), displayName("[2] argument=BAR"), finishedWithFailure(message("BAR"))));
11311135
}
11321136

1133-
@Test
1134-
void executesWithRepeatableValueSource() {
1135-
var results = execute("testWithRepeatableValueSource", String.class);
1137+
@ParameterizedTest
1138+
@ValueSource(strings = { "testWithRepeatableValueSource", "testWithRepeatableValueSourceAsMetaAnnotation" })
1139+
void executesWithRepeatableValueSource(String methodName) {
1140+
var results = execute(methodName, String.class);
11361141
results.allEvents().assertThatEvents() //
11371142
.haveExactly(1, event(test(), displayName("[1] argument=foo"), finishedWithFailure(message("foo")))) //
11381143
.haveExactly(1,
11391144
event(test(), displayName("[2] argument=bar"), finishedWithFailure(message("bar"))));
11401145
}
11411146

1142-
@Test
1143-
void executesWithRepeatableFieldSource() {
1144-
var results = execute("testWithRepeatableFieldSource", String.class);
1147+
@ParameterizedTest
1148+
@ValueSource(strings = { "testWithRepeatableFieldSource", "testWithRepeatableFieldSourceAsMetaAnnotation" })
1149+
void executesWithRepeatableFieldSource(String methodName) {
1150+
var results = execute(methodName, String.class);
11451151
results.allEvents().assertThatEvents() //
11461152
.haveExactly(1,
11471153
event(test(), displayName("[1] argument=some"), finishedWithFailure(message("some")))) //
11481154
.haveExactly(1,
11491155
event(test(), displayName("[2] argument=other"), finishedWithFailure(message("other"))));
11501156
}
11511157

1152-
@Test
1153-
void executesWithRepeatableArgumentsSource() {
1154-
var results = execute("testWithRepeatableArgumentsSource", String.class);
1158+
@ParameterizedTest
1159+
@ValueSource(strings = { "testWithRepeatableArgumentsSource",
1160+
"testWithRepeatableArgumentsSourceAsMetaAnnotation" })
1161+
void executesWithRepeatableArgumentsSource(String methodName) {
1162+
var results = execute(methodName, String.class);
11551163
results.allEvents().assertThatEvents() //
11561164
.haveExactly(1, event(test(), displayName("[1] argument=foo"), finishedWithFailure(message("foo")))) //
11571165
.haveExactly(1, event(test(), displayName("[2] argument=bar"), finishedWithFailure(message("bar")))) //
@@ -1542,7 +1550,7 @@ void testWithNullAndEmptySourceForTwoDimensionalStringArray(String[][] argument)
15421550
static class MethodSourceTestCase {
15431551

15441552
@Target(ElementType.METHOD)
1545-
@Retention(RetentionPolicy.RUNTIME)
1553+
@Retention(RUNTIME)
15461554
@ParameterizedTest(name = "{arguments}")
15471555
@MethodSource
15481556
@interface MethodSourceTest {
@@ -1767,7 +1775,7 @@ private static Stream<String> test() {
17671775
static class FieldSourceTestCase {
17681776

17691777
@Target(ElementType.METHOD)
1770-
@Retention(RetentionPolicy.RUNTIME)
1778+
@Retention(RUNTIME)
17711779
@ParameterizedTest(name = "{arguments}")
17721780
@FieldSource
17731781
@interface FieldSourceTest {
@@ -2035,20 +2043,56 @@ void testWithRepeatableCsvFileSource(String column1, String column2) {
20352043
fail("%s %s".formatted(column1, column2));
20362044
}
20372045

2046+
@CsvFileSource(resources = "two-column.csv")
2047+
@CsvFileSource(resources = "two-column-with-headers.csv", delimiter = '|', useHeadersInDisplayName = true, nullValues = "NIL")
2048+
@Retention(RUNTIME)
2049+
@interface TwoCsvFileSources {
2050+
}
2051+
2052+
@ParameterizedTest
2053+
@TwoCsvFileSources
2054+
void testWithRepeatableCsvFileSourceAsMetaAnnotation(String column1, String column2) {
2055+
fail("%s %s".formatted(column1, column2));
2056+
}
2057+
20382058
@ParameterizedTest
20392059
@CsvSource({ "a" })
20402060
@CsvSource({ "b" })
20412061
void testWithRepeatableCsvSource(String argument) {
20422062
fail(argument);
20432063
}
20442064

2065+
@CsvSource({ "a" })
2066+
@CsvSource({ "b" })
2067+
@Retention(RUNTIME)
2068+
@interface TwoCsvSources {
2069+
}
2070+
2071+
@ParameterizedTest
2072+
@TwoCsvSources
2073+
void testWithRepeatableCsvSourceAsMetaAnnotation(String argument) {
2074+
fail(argument);
2075+
}
2076+
20452077
@ParameterizedTest
20462078
@EnumSource(SmartAction.class)
20472079
@EnumSource(QuickAction.class)
20482080
void testWithRepeatableEnumSource(Action argument) {
20492081
fail(argument.toString());
20502082
}
20512083

2084+
@EnumSource(SmartAction.class)
2085+
@EnumSource(QuickAction.class)
2086+
@Retention(RUNTIME)
2087+
@interface TwoEnumSources {
2088+
}
2089+
2090+
@ParameterizedTest
2091+
@TwoEnumSources
2092+
void testWithRepeatableEnumSourceAsMetaAnnotation(Action argument) {
2093+
fail(argument.toString());
2094+
}
2095+
20522096
interface Action {
20532097
}
20542098

@@ -2067,6 +2111,18 @@ void testWithRepeatableMethodSource(String argument) {
20672111
fail(argument);
20682112
}
20692113

2114+
@MethodSource("someArgumentsMethodSource")
2115+
@MethodSource("otherArgumentsMethodSource")
2116+
@Retention(RUNTIME)
2117+
@interface TwoMethodSources {
2118+
}
2119+
2120+
@ParameterizedTest
2121+
@TwoMethodSources
2122+
void testWithRepeatableMethodSourceAsMetaAnnotation(String argument) {
2123+
fail(argument);
2124+
}
2125+
20702126
public static Stream<Arguments> someArgumentsMethodSource() {
20712127
return Stream.of(Arguments.of("some"));
20722128
}
@@ -2082,6 +2138,18 @@ void testWithRepeatableFieldSource(String argument) {
20822138
fail(argument);
20832139
}
20842140

2141+
@FieldSource("someArgumentsContainer")
2142+
@FieldSource("otherArgumentsContainer")
2143+
@Retention(RUNTIME)
2144+
@interface TwoFieldSources {
2145+
}
2146+
2147+
@ParameterizedTest
2148+
@TwoFieldSources
2149+
void testWithRepeatableFieldSourceAsMetaAnnotation(String argument) {
2150+
fail(argument);
2151+
}
2152+
20852153
static List<String> someArgumentsContainer = List.of("some");
20862154
static List<String> otherArgumentsContainer = List.of("other");
20872155

@@ -2092,6 +2160,18 @@ void testWithRepeatableValueSource(String argument) {
20922160
fail(argument);
20932161
}
20942162

2163+
@ValueSource(strings = "foo")
2164+
@ValueSource(strings = "bar")
2165+
@Retention(RUNTIME)
2166+
@interface TwoValueSources {
2167+
}
2168+
2169+
@ParameterizedTest
2170+
@TwoValueSources
2171+
void testWithRepeatableValueSourceAsMetaAnnotation(String argument) {
2172+
fail(argument);
2173+
}
2174+
20952175
@ParameterizedTest
20962176
@ValueSource(strings = "foo")
20972177
@ValueSource(strings = "foo")
@@ -2117,6 +2197,18 @@ void testWithDifferentRepeatableAnnotations(String argument) {
21172197
void testWithRepeatableArgumentsSource(String argument) {
21182198
fail(argument);
21192199
}
2200+
2201+
@ArgumentsSource(TwoSingleStringArgumentsProvider.class)
2202+
@ArgumentsSource(TwoUnusedStringArgumentsProvider.class)
2203+
@Retention(RUNTIME)
2204+
@interface TwoArgumentsSources {
2205+
}
2206+
2207+
@ParameterizedTest
2208+
@TwoArgumentsSources
2209+
void testWithRepeatableArgumentsSourceAsMetaAnnotation(String argument) {
2210+
fail(argument);
2211+
}
21202212
}
21212213

21222214
private static class TwoSingleStringArgumentsProvider implements ArgumentsProvider {

platform-tooling-support-tests/src/test/java/platform/tooling/support/tests/ArchUnitTests.java

-3
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
import static com.tngtech.archunit.core.domain.JavaClass.Predicates.simpleName;
2020
import static com.tngtech.archunit.core.domain.JavaClass.Predicates.type;
2121
import static com.tngtech.archunit.core.domain.JavaModifier.PUBLIC;
22-
import static com.tngtech.archunit.core.domain.properties.CanBeAnnotated.Predicates.annotatedWith;
2322
import static com.tngtech.archunit.core.domain.properties.HasModifiers.Predicates.modifier;
2423
import static com.tngtech.archunit.core.domain.properties.HasName.Predicates.name;
2524
import static com.tngtech.archunit.core.domain.properties.HasName.Predicates.nameContaining;
@@ -54,7 +53,6 @@
5453
import org.apiguardian.api.API;
5554
import org.junit.jupiter.api.Order;
5655
import org.junit.jupiter.api.extension.ExtendWith;
57-
import org.junit.jupiter.params.provider.ArgumentsSource;
5856

5957
@Order(Integer.MAX_VALUE)
6058
@AnalyzeClasses(locations = ArchUnitTests.AllJars.class)
@@ -77,7 +75,6 @@ class ArchUnitTests {
7775
.and().areAnnotations() //
7876
.and().areAnnotatedWith(Repeatable.class) //
7977
.and(are(not(type(ExtendWith.class)))) // to be resolved in https://github.com/junit-team/junit5/issues/4059
80-
.and(are(not(type(ArgumentsSource.class).or(annotatedWith(ArgumentsSource.class))))) // to be resolved in https://github.com/junit-team/junit5/issues/4063
8178
.should(haveContainerAnnotationWithSameRetentionPolicy()) //
8279
.andShould(haveContainerAnnotationWithSameTargetTypes());
8380

0 commit comments

Comments
 (0)