2020import java .lang .annotation .Repeatable ;
2121import java .lang .annotation .Retention ;
2222import java .lang .annotation .RetentionPolicy ;
23+ import java .util .Arrays ;
2324
25+ import org .junit .jupiter .api .Nested ;
2426import org .junit .jupiter .api .Test ;
2527
2628import static org .assertj .core .api .Assertions .assertThat ;
3133 * Tests for {@link RepeatableContainers}.
3234 *
3335 * @author Phillip Webb
36+ * @author Sam Brannen
3437 */
3538class RepeatableContainersTests {
3639
37- @ Test
38- void standardRepeatablesWhenNonRepeatableReturnsNull () {
39- Object [] values = findRepeatedAnnotationValues (
40- RepeatableContainers .standardRepeatables (), WithNonRepeatable .class ,
41- NonRepeatable .class );
42- assertThat (values ).isNull ();
43- }
40+ @ Nested
41+ class StandardRepeatableContainersTests {
4442
45- @ Test
46- void standardRepeatablesWhenSingleReturnsNull () {
47- Object [] values = findRepeatedAnnotationValues (
48- RepeatableContainers .standardRepeatables (),
49- WithSingleStandardRepeatable .class , StandardRepeatable .class );
50- assertThat (values ).isNull ();
51- }
43+ @ Test
44+ void standardRepeatablesWhenNonRepeatableReturnsNull () {
45+ Object [] values = findRepeatedAnnotationValues (RepeatableContainers .standardRepeatables (),
46+ NonRepeatableTestCase .class , NonRepeatable .class );
47+ assertThat (values ).isNull ();
48+ }
5249
53- @ Test
54- void standardRepeatablesWhenContainerReturnsRepeats () {
55- Object [] values = findRepeatedAnnotationValues (
56- RepeatableContainers .standardRepeatables (), WithStandardRepeatables .class ,
57- StandardContainer .class );
58- assertThat (values ).containsExactly ("a" , "b" );
59- }
50+ @ Test
51+ void standardRepeatablesWhenSingleReturnsNull () {
52+ Object [] values = findRepeatedAnnotationValues (RepeatableContainers .standardRepeatables (),
53+ SingleStandardRepeatableTestCase .class , StandardRepeatable .class );
54+ assertThat (values ).isNull ();
55+ }
6056
61- @ Test
62- void standardRepeatablesWhenContainerButNotRepeatableReturnsNull () {
63- Object [] values = findRepeatedAnnotationValues (
64- RepeatableContainers .standardRepeatables (), WithExplicitRepeatables .class ,
65- ExplicitContainer .class );
66- assertThat (values ).isNull ();
67- }
57+ @ Test
58+ void standardRepeatablesWhenContainerButNotRepeatableReturnsNull () {
59+ Object [] values = findRepeatedAnnotationValues (RepeatableContainers .standardRepeatables (),
60+ ExplicitRepeatablesTestCase .class , ExplicitContainer .class );
61+ assertThat (values ).isNull ();
62+ }
6863
69- @ Test
70- void ofExplicitWhenNonRepeatableReturnsNull () {
71- Object [] values = findRepeatedAnnotationValues (
72- RepeatableContainers .of (ExplicitRepeatable .class ,
73- ExplicitContainer .class ),
74- WithNonRepeatable .class , NonRepeatable .class );
75- assertThat (values ).isNull ();
64+ @ Test
65+ void standardRepeatablesWhenContainerReturnsRepeats () {
66+ Object [] values = findRepeatedAnnotationValues (RepeatableContainers .standardRepeatables (),
67+ StandardRepeatablesTestCase .class , StandardContainer .class );
68+ assertThat (values ).containsExactly ("a" , "b" );
69+ }
7670 }
7771
78- @ Test
79- void ofExplicitWhenStandardRepeatableContainerReturnsNull () {
80- Object [] values = findRepeatedAnnotationValues (
81- RepeatableContainers .of (ExplicitRepeatable .class ,
82- ExplicitContainer .class ),
83- WithStandardRepeatables .class , StandardContainer .class );
84- assertThat (values ).isNull ();
85- }
72+ @ Nested
73+ class ExplicitRepeatableContainerTests {
8674
87- @ Test
88- void ofExplicitWhenContainerReturnsRepeats () {
89- Object [] values = findRepeatedAnnotationValues (
90- RepeatableContainers .of (ExplicitRepeatable .class ,
91- ExplicitContainer .class ),
92- WithExplicitRepeatables .class , ExplicitContainer .class );
93- assertThat (values ).containsExactly ("a" , "b" );
94- }
75+ @ Test
76+ void ofExplicitWhenNonRepeatableReturnsNull () {
77+ Object [] values = findRepeatedAnnotationValues (
78+ RepeatableContainers .of (ExplicitRepeatable .class , ExplicitContainer .class ),
79+ NonRepeatableTestCase .class , NonRepeatable .class );
80+ assertThat (values ).isNull ();
81+ }
9582
96- @ Test
97- void ofExplicitWhenHasNoValueThrowsException () {
98- assertThatExceptionOfType (AnnotationConfigurationException .class ).isThrownBy (() ->
99- RepeatableContainers .of (ExplicitRepeatable .class , InvalidNoValue .class ))
100- .withMessageContaining ("Invalid declaration of container type ["
101- + InvalidNoValue .class .getName ()
102- + "] for repeatable annotation ["
103- + ExplicitRepeatable .class .getName () + "]" );
104- }
83+ @ Test
84+ void ofExplicitWhenStandardRepeatableContainerReturnsNull () {
85+ Object [] values = findRepeatedAnnotationValues (
86+ RepeatableContainers .of (ExplicitRepeatable .class , ExplicitContainer .class ),
87+ StandardRepeatablesTestCase .class , StandardContainer .class );
88+ assertThat (values ).isNull ();
89+ }
10590
106- @ Test
107- void ofExplicitWhenValueIsNotArrayThrowsException () {
108- assertThatExceptionOfType (AnnotationConfigurationException .class ).isThrownBy (() ->
109- RepeatableContainers .of (ExplicitRepeatable .class , InvalidNotArray .class ))
110- .withMessage ("Container type ["
111- + InvalidNotArray .class .getName ()
112- + "] must declare a 'value' attribute for an array of type ["
113- + ExplicitRepeatable .class .getName () + "]" );
114- }
91+ @ Test
92+ void ofExplicitWhenContainerReturnsRepeats () {
93+ Object [] values = findRepeatedAnnotationValues (
94+ RepeatableContainers .of (ExplicitRepeatable .class , ExplicitContainer .class ),
95+ ExplicitRepeatablesTestCase .class , ExplicitContainer .class );
96+ assertThat (values ).containsExactly ("a" , "b" );
97+ }
11598
116- @ Test
117- void ofExplicitWhenValueIsArrayOfWrongTypeThrowsException () {
118- assertThatExceptionOfType (AnnotationConfigurationException .class ).isThrownBy (() ->
119- RepeatableContainers .of (ExplicitRepeatable .class , InvalidWrongArrayType .class ))
120- .withMessage ("Container type ["
121- + InvalidWrongArrayType .class .getName ()
122- + "] must declare a 'value' attribute for an array of type ["
123- + ExplicitRepeatable .class .getName () + "]" );
124- }
99+ @ Test
100+ void ofExplicitWhenContainerIsNullDeducesContainer () {
101+ Object [] values = findRepeatedAnnotationValues (RepeatableContainers .of (StandardRepeatable .class , null ),
102+ StandardRepeatablesTestCase .class , StandardContainer .class );
103+ assertThat (values ).containsExactly ("a" , "b" );
104+ }
125105
126- @ Test
127- void ofExplicitWhenAnnotationIsNullThrowsException () {
128- assertThatIllegalArgumentException ().isThrownBy (() ->
129- RepeatableContainers .of (null , null ))
130- .withMessage ("Repeatable must not be null" );
131- }
106+ @ Test
107+ void ofExplicitWhenHasNoValueThrowsException () {
108+ assertThatExceptionOfType (AnnotationConfigurationException .class )
109+ .isThrownBy (() -> RepeatableContainers .of (ExplicitRepeatable .class , InvalidNoValue .class ))
110+ .withMessageContaining ("Invalid declaration of container type [%s] for repeatable annotation [%s]" ,
111+ InvalidNoValue .class .getName (), ExplicitRepeatable .class .getName ());
112+ }
132113
133- @ Test
134- void ofExplicitWhenContainerIsNullDeducesContainer () {
135- Object [] values = findRepeatedAnnotationValues (
136- RepeatableContainers .of (StandardRepeatable .class , null ),
137- WithStandardRepeatables .class , StandardContainer .class );
138- assertThat (values ).containsExactly ("a" , "b" );
139- }
114+ @ Test
115+ void ofExplicitWhenValueIsNotArrayThrowsException () {
116+ assertThatExceptionOfType (AnnotationConfigurationException .class )
117+ .isThrownBy (() -> RepeatableContainers .of (ExplicitRepeatable .class , InvalidNotArray .class ))
118+ .withMessage ("Container type [%s] must declare a 'value' attribute for an array of type [%s]" ,
119+ InvalidNotArray .class .getName (), ExplicitRepeatable .class .getName ());
120+ }
121+
122+ @ Test
123+ void ofExplicitWhenValueIsArrayOfWrongTypeThrowsException () {
124+ assertThatExceptionOfType (AnnotationConfigurationException .class )
125+ .isThrownBy (() -> RepeatableContainers .of (ExplicitRepeatable .class , InvalidWrongArrayType .class ))
126+ .withMessage ("Container type [%s] must declare a 'value' attribute for an array of type [%s]" ,
127+ InvalidWrongArrayType .class .getName (), ExplicitRepeatable .class .getName ());
128+ }
129+
130+ @ Test
131+ void ofExplicitWhenAnnotationIsNullThrowsException () {
132+ assertThatIllegalArgumentException ()
133+ .isThrownBy (() -> RepeatableContainers .of (null , null ))
134+ .withMessage ("Repeatable must not be null" );
135+ }
136+
137+ @ Test
138+ void ofExplicitWhenContainerIsNullAndNotRepeatableThrowsException () {
139+ assertThatIllegalArgumentException ()
140+ .isThrownBy (() -> RepeatableContainers .of (ExplicitRepeatable .class , null ))
141+ .withMessage ("Annotation type must be a repeatable annotation: failed to resolve container type for %s" ,
142+ ExplicitRepeatable .class .getName ());
143+ }
140144
141- @ Test
142- void ofExplicitWhenContainerIsNullAndNotRepeatableThrowsException () {
143- assertThatIllegalArgumentException ().isThrownBy (() ->
144- RepeatableContainers .of (ExplicitRepeatable .class , null ))
145- .withMessage ("Annotation type must be a repeatable annotation: " +
146- "failed to resolve container type for " +
147- ExplicitRepeatable .class .getName ());
148145 }
149146
150147 @ Test
151148 void standardAndExplicitReturnsRepeats () {
152- RepeatableContainers repeatableContainers = RepeatableContainers .standardRepeatables ().and (
153- ExplicitContainer .class , ExplicitRepeatable .class );
154- assertThat (findRepeatedAnnotationValues (repeatableContainers ,
155- WithStandardRepeatables .class , StandardContainer .class )).containsExactly (
156- "a" , "b" );
157- assertThat (findRepeatedAnnotationValues (repeatableContainers ,
158- WithExplicitRepeatables .class , ExplicitContainer .class )).containsExactly (
159- "a" , "b" );
149+ RepeatableContainers repeatableContainers = RepeatableContainers .standardRepeatables ()
150+ .and (ExplicitContainer .class , ExplicitRepeatable .class );
151+ assertThat (findRepeatedAnnotationValues (repeatableContainers , StandardRepeatablesTestCase .class , StandardContainer .class ))
152+ .containsExactly ("a" , "b" );
153+ assertThat (findRepeatedAnnotationValues (repeatableContainers , ExplicitRepeatablesTestCase .class , ExplicitContainer .class ))
154+ .containsExactly ("a" , "b" );
160155 }
161156
162157 @ Test
163158 void noneAlwaysReturnsNull () {
164- Object [] values = findRepeatedAnnotationValues (
165- RepeatableContainers .none (), WithStandardRepeatables .class ,
166- StandardContainer .class );
159+ Object [] values = findRepeatedAnnotationValues (RepeatableContainers .none (), StandardRepeatablesTestCase .class ,
160+ StandardContainer .class );
167161 assertThat (values ).isNull ();
168162 }
169163
170164 @ Test
171165 void equalsAndHashcode () {
172- RepeatableContainers c1 = RepeatableContainers .of (ExplicitRepeatable .class ,
173- ExplicitContainer .class );
174- RepeatableContainers c2 = RepeatableContainers .of (ExplicitRepeatable .class ,
175- ExplicitContainer .class );
166+ RepeatableContainers c1 = RepeatableContainers .of (ExplicitRepeatable .class , ExplicitContainer .class );
167+ RepeatableContainers c2 = RepeatableContainers .of (ExplicitRepeatable .class , ExplicitContainer .class );
176168 RepeatableContainers c3 = RepeatableContainers .standardRepeatables ();
177- RepeatableContainers c4 = RepeatableContainers .standardRepeatables ().and (
178- ExplicitContainer .class , ExplicitRepeatable .class );
179- assertThat (c1 .hashCode ()).isEqualTo (c2 .hashCode ());
169+ RepeatableContainers c4 = RepeatableContainers .standardRepeatables ().and (ExplicitContainer .class , ExplicitRepeatable .class );
170+ assertThat (c1 ).hasSameHashCodeAs (c2 );
180171 assertThat (c1 ).isEqualTo (c1 ).isEqualTo (c2 );
181172 assertThat (c1 ).isNotEqualTo (c3 ).isNotEqualTo (c4 );
182173 }
183174
184- private Object [] findRepeatedAnnotationValues (RepeatableContainers containers ,
175+
176+ private static Object [] findRepeatedAnnotationValues (RepeatableContainers containers ,
185177 Class <?> element , Class <? extends Annotation > annotationType ) {
186- Annotation [] annotations = containers .findRepeatedAnnotations (
187- element .getAnnotation (annotationType ));
178+ Annotation [] annotations = containers .findRepeatedAnnotations (element .getAnnotation (annotationType ));
188179 return extractValues (annotations );
189180 }
190181
191- private Object [] extractValues (Annotation [] annotations ) {
192- try {
193- if (annotations == null ) {
194- return null ;
195- }
196- Object [] result = new String [annotations .length ];
197- for (int i = 0 ; i < annotations .length ; i ++) {
198- result [i ] = annotations [i ].annotationType ().getMethod ("value" ).invoke (
199- annotations [i ]);
200- }
201- return result ;
202- }
203- catch (Exception ex ) {
204- throw new RuntimeException (ex );
182+ private static Object [] extractValues (Annotation [] annotations ) {
183+ if (annotations == null ) {
184+ return null ;
205185 }
186+ return Arrays .stream (annotations ).map (AnnotationUtils ::getValue ).toArray (Object []::new );
206187 }
207188
208- @ Retention (RetentionPolicy .RUNTIME )
209- @interface NonRepeatable {
210-
211- String value () default "" ;
212- }
213189
214190 @ Retention (RetentionPolicy .RUNTIME )
215- @ Repeatable (StandardContainer .class )
216- @interface StandardRepeatable {
191+ @interface NonRepeatable {
217192
218193 String value () default "" ;
219194 }
@@ -225,7 +200,8 @@ private Object[] extractValues(Annotation[] annotations) {
225200 }
226201
227202 @ Retention (RetentionPolicy .RUNTIME )
228- @interface ExplicitRepeatable {
203+ @ Repeatable (StandardContainer .class )
204+ @interface StandardRepeatable {
229205
230206 String value () default "" ;
231207 }
@@ -236,6 +212,12 @@ private Object[] extractValues(Annotation[] annotations) {
236212 ExplicitRepeatable [] value ();
237213 }
238214
215+ @ Retention (RetentionPolicy .RUNTIME )
216+ @interface ExplicitRepeatable {
217+
218+ String value () default "" ;
219+ }
220+
239221 @ Retention (RetentionPolicy .RUNTIME )
240222 @interface InvalidNoValue {
241223 }
@@ -253,20 +235,20 @@ private Object[] extractValues(Annotation[] annotations) {
253235 }
254236
255237 @ NonRepeatable ("a" )
256- static class WithNonRepeatable {
238+ static class NonRepeatableTestCase {
257239 }
258240
259241 @ StandardRepeatable ("a" )
260- static class WithSingleStandardRepeatable {
242+ static class SingleStandardRepeatableTestCase {
261243 }
262244
263245 @ StandardRepeatable ("a" )
264246 @ StandardRepeatable ("b" )
265- static class WithStandardRepeatables {
247+ static class StandardRepeatablesTestCase {
266248 }
267249
268250 @ ExplicitContainer ({ @ ExplicitRepeatable ("a" ), @ ExplicitRepeatable ("b" ) })
269- static class WithExplicitRepeatables {
251+ static class ExplicitRepeatablesTestCase {
270252 }
271253
272254}
0 commit comments