Skip to content

Commit 323dbb9

Browse files
committed
Move convention-based attribute override tests to @nested class
1 parent 63d7e81 commit 323dbb9

File tree

2 files changed

+87
-80
lines changed

2 files changed

+87
-80
lines changed

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

Lines changed: 86 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2019 the original author or authors.
2+
* Copyright 2002-2022 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -36,6 +36,7 @@
3636
import javax.annotation.meta.When;
3737

3838
import org.junit.jupiter.api.Disabled;
39+
import org.junit.jupiter.api.Nested;
3940
import org.junit.jupiter.api.Test;
4041

4142
import org.springframework.core.annotation.AnnotationUtilsTests.ExtendsBaseClassWithGenericAnnotatedMethod;
@@ -82,6 +83,90 @@ class AnnotatedElementUtilsTests {
8283
private static final String TX_NAME = Transactional.class.getName();
8384

8485

86+
@Nested
87+
class ConventionBasedAnnotationAttributeOverrideTests {
88+
89+
@Test
90+
void getMergedAnnotationAttributesWithConventionBasedComposedAnnotation() {
91+
Class<?> element = ConventionBasedComposedContextConfigClass.class;
92+
String name = ContextConfig.class.getName();
93+
AnnotationAttributes attributes = getMergedAnnotationAttributes(element, name);
94+
95+
assertThat(attributes).as("Should find @ContextConfig on " + element.getSimpleName()).isNotNull();
96+
assertThat(attributes.getStringArray("locations")).as("locations").containsExactly("explicitDeclaration");
97+
assertThat(attributes.getStringArray("value")).as("value").containsExactly("explicitDeclaration");
98+
99+
// Verify contracts between utility methods:
100+
assertThat(isAnnotated(element, name)).isTrue();
101+
}
102+
103+
/**
104+
* This test should never pass, simply because Spring does not support a hybrid
105+
* approach for annotation attribute overrides with transitive implicit aliases.
106+
* See SPR-13554 for details.
107+
* <p>Furthermore, if you choose to execute this test, it can fail for either
108+
* the first test class or the second one (with different exceptions), depending
109+
* on the order in which the JVM returns the attribute methods via reflection.
110+
*/
111+
@Disabled("Permanently disabled but left in place for illustrative purposes")
112+
@Test
113+
void getMergedAnnotationAttributesWithHalfConventionBasedAndHalfAliasedComposedAnnotation() {
114+
for (Class<?> clazz : asList(HalfConventionBasedAndHalfAliasedComposedContextConfigClassV1.class,
115+
HalfConventionBasedAndHalfAliasedComposedContextConfigClassV2.class)) {
116+
getMergedAnnotationAttributesWithHalfConventionBasedAndHalfAliasedComposedAnnotation(clazz);
117+
}
118+
}
119+
120+
private void getMergedAnnotationAttributesWithHalfConventionBasedAndHalfAliasedComposedAnnotation(Class<?> clazz) {
121+
String name = ContextConfig.class.getName();
122+
String simpleName = clazz.getSimpleName();
123+
AnnotationAttributes attributes = getMergedAnnotationAttributes(clazz, name);
124+
125+
assertThat(attributes).as("Should find @ContextConfig on " + simpleName).isNotNull();
126+
assertThat(attributes.getStringArray("locations")).as("locations for class [" + simpleName + "]")
127+
.containsExactly("explicitDeclaration");
128+
assertThat(attributes.getStringArray("value")).as("value for class [" + simpleName + "]")
129+
.containsExactly("explicitDeclaration");
130+
131+
// Verify contracts between utility methods:
132+
assertThat(isAnnotated(clazz, name)).isTrue();
133+
}
134+
135+
@Test
136+
void getMergedAnnotationAttributesWithInvalidConventionBasedComposedAnnotation() {
137+
Class<?> element = InvalidConventionBasedComposedContextConfigClass.class;
138+
assertThatExceptionOfType(AnnotationConfigurationException.class).isThrownBy(() ->
139+
getMergedAnnotationAttributes(element, ContextConfig.class))
140+
.withMessageContaining("Different @AliasFor mirror values for annotation")
141+
.withMessageContaining("attribute 'locations' and its alias 'value'")
142+
.withMessageContaining("values of [{requiredLocationsDeclaration}] and [{duplicateDeclaration}]");
143+
}
144+
145+
@Test
146+
void findMergedAnnotationAttributesWithSingleElementOverridingAnArrayViaConvention() {
147+
assertComponentScanAttributes(ConventionBasedSinglePackageComponentScanClass.class, "com.example.app.test");
148+
}
149+
150+
@Test
151+
void findMergedAnnotationWithLocalAliasesThatConflictWithAttributesInMetaAnnotationByConvention() {
152+
Class<?> element = SpringAppConfigClass.class;
153+
ContextConfig contextConfig = findMergedAnnotation(element, ContextConfig.class);
154+
155+
assertThat(contextConfig).as("Should find @ContextConfig on " + element).isNotNull();
156+
assertThat(contextConfig.locations()).as("locations for " + element).isEmpty();
157+
// 'value' in @SpringAppConfig should not override 'value' in @ContextConfig
158+
assertThat(contextConfig.value()).as("value for " + element).isEmpty();
159+
assertThat(contextConfig.classes()).as("classes for " + element).containsExactly(Number.class);
160+
}
161+
162+
@Test
163+
void findMergedAnnotationWithSingleElementOverridingAnArrayViaConvention() throws Exception {
164+
assertWebMapping(WebController.class.getMethod("postMappedWithPathAttribute"));
165+
}
166+
167+
}
168+
169+
85170
@Test
86171
void getMetaAnnotationTypesOnNonAnnotatedClass() {
87172
assertThat(getMetaAnnotationTypes(NonAnnotatedClass.class, TransactionalComponent.class).isEmpty()).isTrue();
@@ -363,51 +448,6 @@ void getMergedAnnotationAttributesOnNonInheritedAnnotationInterface() {
363448
assertThat(isAnnotated(element, name)).isTrue();
364449
}
365450

366-
@Test
367-
void getMergedAnnotationAttributesWithConventionBasedComposedAnnotation() {
368-
Class<?> element = ConventionBasedComposedContextConfigClass.class;
369-
String name = ContextConfig.class.getName();
370-
AnnotationAttributes attributes = getMergedAnnotationAttributes(element, name);
371-
372-
assertThat(attributes).as("Should find @ContextConfig on " + element.getSimpleName()).isNotNull();
373-
assertThat(attributes.getStringArray("locations")).as("locations").isEqualTo(asArray("explicitDeclaration"));
374-
assertThat(attributes.getStringArray("value")).as("value").isEqualTo(asArray("explicitDeclaration"));
375-
376-
// Verify contracts between utility methods:
377-
assertThat(isAnnotated(element, name)).isTrue();
378-
}
379-
380-
/**
381-
* This test should never pass, simply because Spring does not support a hybrid
382-
* approach for annotation attribute overrides with transitive implicit aliases.
383-
* See SPR-13554 for details.
384-
* <p>Furthermore, if you choose to execute this test, it can fail for either
385-
* the first test class or the second one (with different exceptions), depending
386-
* on the order in which the JVM returns the attribute methods via reflection.
387-
*/
388-
@Disabled("Permanently disabled but left in place for illustrative purposes")
389-
@Test
390-
void getMergedAnnotationAttributesWithHalfConventionBasedAndHalfAliasedComposedAnnotation() {
391-
for (Class<?> clazz : asList(HalfConventionBasedAndHalfAliasedComposedContextConfigClassV1.class,
392-
HalfConventionBasedAndHalfAliasedComposedContextConfigClassV2.class)) {
393-
getMergedAnnotationAttributesWithHalfConventionBasedAndHalfAliasedComposedAnnotation(clazz);
394-
}
395-
}
396-
397-
private void getMergedAnnotationAttributesWithHalfConventionBasedAndHalfAliasedComposedAnnotation(Class<?> clazz) {
398-
String[] expected = asArray("explicitDeclaration");
399-
String name = ContextConfig.class.getName();
400-
String simpleName = clazz.getSimpleName();
401-
AnnotationAttributes attributes = getMergedAnnotationAttributes(clazz, name);
402-
403-
assertThat(attributes).as("Should find @ContextConfig on " + simpleName).isNotNull();
404-
assertThat(attributes.getStringArray("locations")).as("locations for class [" + clazz.getSimpleName() + "]").isEqualTo(expected);
405-
assertThat(attributes.getStringArray("value")).as("value for class [" + clazz.getSimpleName() + "]").isEqualTo(expected);
406-
407-
// Verify contracts between utility methods:
408-
assertThat(isAnnotated(clazz, name)).isTrue();
409-
}
410-
411451
@Test
412452
void getMergedAnnotationAttributesWithAliasedComposedAnnotation() {
413453
Class<?> element = AliasedComposedContextConfigClass.class;
@@ -530,16 +570,6 @@ void getMergedAnnotationWithImplicitAliasesWithDefaultsInMetaAnnotationOnCompose
530570
assertThat(isAnnotated(element, name)).isTrue();
531571
}
532572

533-
@Test
534-
void getMergedAnnotationAttributesWithInvalidConventionBasedComposedAnnotation() {
535-
Class<?> element = InvalidConventionBasedComposedContextConfigClass.class;
536-
assertThatExceptionOfType(AnnotationConfigurationException.class).isThrownBy(() ->
537-
getMergedAnnotationAttributes(element, ContextConfig.class))
538-
.withMessageContaining("Different @AliasFor mirror values for annotation")
539-
.withMessageContaining("attribute 'locations' and its alias 'value'")
540-
.withMessageContaining("values of [{requiredLocationsDeclaration}] and [{duplicateDeclaration}]");
541-
}
542-
543573
@Test
544574
void getMergedAnnotationAttributesWithShadowedAliasComposedAnnotation() {
545575
Class<?> element = ShadowedAliasComposedContextConfigClass.class;
@@ -743,11 +773,6 @@ void findMergedAnnotationOnClassWithComposedMetaTransactionalAnnotation() throws
743773
assertThat(annotation.qualifier()).as("TX qualifier for " + clazz).isEqualTo("anotherTransactionManager");
744774
}
745775

746-
@Test
747-
void findMergedAnnotationAttributesWithSingleElementOverridingAnArrayViaConvention() {
748-
assertComponentScanAttributes(ConventionBasedSinglePackageComponentScanClass.class, "com.example.app.test");
749-
}
750-
751776
@Test
752777
void findMergedAnnotationAttributesWithSingleElementOverridingAnArrayViaAliasFor() {
753778
assertComponentScanAttributes(AliasForBasedSinglePackageComponentScanClass.class, "com.example.app.test");
@@ -800,24 +825,6 @@ void findMergedAnnotationForMultipleMetaAnnotationsWithClashingAttributeNames()
800825
assertThat(testPropSource.value()).as("value").isEqualTo(propFiles);
801826
}
802827

803-
@Test
804-
void findMergedAnnotationWithLocalAliasesThatConflictWithAttributesInMetaAnnotationByConvention() {
805-
final String[] EMPTY = new String[0];
806-
Class<?> element = SpringAppConfigClass.class;
807-
ContextConfig contextConfig = findMergedAnnotation(element, ContextConfig.class);
808-
809-
assertThat(contextConfig).as("Should find @ContextConfig on " + element).isNotNull();
810-
assertThat(contextConfig.locations()).as("locations for " + element).isEqualTo(EMPTY);
811-
// 'value' in @SpringAppConfig should not override 'value' in @ContextConfig
812-
assertThat(contextConfig.value()).as("value for " + element).isEqualTo(EMPTY);
813-
assertThat(contextConfig.classes()).as("classes for " + element).isEqualTo(new Class<?>[] {Number.class});
814-
}
815-
816-
@Test
817-
void findMergedAnnotationWithSingleElementOverridingAnArrayViaConvention() throws Exception {
818-
assertWebMapping(WebController.class.getMethod("postMappedWithPathAttribute"));
819-
}
820-
821828
@Test
822829
void findMergedAnnotationWithSingleElementOverridingAnArrayViaAliasFor() throws Exception {
823830
assertWebMapping(WebController.class.getMethod("getMappedWithValueAttribute"));

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ void getWithInheritedAnnotationsFromHalfConventionBasedAndHalfAliasedComposedAnn
101101
}
102102

103103
@Test
104-
void withInheritedAnnotationsFromHalfConventionBasedAndHalfAliasedComposedAnnotation2() {
104+
void getWithInheritedAnnotationsFromHalfConventionBasedAndHalfAliasedComposedAnnotation2() {
105105
// SPR-13554: convention mapping mixed with AliasFor annotations
106106
// locations doesn't apply because it has no AliasFor annotation
107107
MergedAnnotation<?> annotation =

0 commit comments

Comments
 (0)