Skip to content

Commit b2ce54e

Browse files
committed
Revise RepeatableContainersTests
1 parent 937ab5f commit b2ce54e

File tree

1 file changed

+127
-145
lines changed

1 file changed

+127
-145
lines changed

spring-core/src/test/java/org/springframework/core/annotation/RepeatableContainersTests.java

Lines changed: 127 additions & 145 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@
2020
import java.lang.annotation.Repeatable;
2121
import java.lang.annotation.Retention;
2222
import java.lang.annotation.RetentionPolicy;
23+
import java.util.Arrays;
2324

25+
import org.junit.jupiter.api.Nested;
2426
import org.junit.jupiter.api.Test;
2527

2628
import static org.assertj.core.api.Assertions.assertThat;
@@ -31,189 +33,162 @@
3133
* Tests for {@link RepeatableContainers}.
3234
*
3335
* @author Phillip Webb
36+
* @author Sam Brannen
3437
*/
3538
class 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

Comments
 (0)