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

Lines changed: 2 additions & 0 deletions
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

Lines changed: 1 addition & 1 deletion
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

Lines changed: 1 addition & 1 deletion
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

Lines changed: 1 addition & 1 deletion
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

Lines changed: 1 addition & 1 deletion
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

Lines changed: 1 addition & 1 deletion
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

Lines changed: 1 addition & 1 deletion
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

Lines changed: 1 addition & 1 deletion
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

Lines changed: 116 additions & 24 deletions
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

Lines changed: 0 additions & 3 deletions
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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy