31
31
import org .apache .commons .logging .LogFactory ;
32
32
import org .springframework .context .ApplicationContextInitializer ;
33
33
import org .springframework .context .ConfigurableApplicationContext ;
34
+ import org .springframework .core .annotation .AnnotationAttributes ;
34
35
import org .springframework .core .annotation .AnnotationUtils ;
35
36
import org .springframework .test .context .MetaAnnotationUtils .AnnotationDescriptor ;
36
37
import org .springframework .test .context .MetaAnnotationUtils .UntypedAnnotationDescriptor ;
@@ -192,9 +193,9 @@ static Class<? extends ContextLoader> resolveContextLoaderClass(Class<?> testCla
192
193
}
193
194
194
195
/**
195
- * Convenience method for creating a {@link ContextConfigurationAttributes} instance
196
- * from the supplied {@link ContextConfiguration} and declaring class and then adding
197
- * the attributes to the supplied list.
196
+ * Convenience method for creating a {@link ContextConfigurationAttributes}
197
+ * instance from the supplied {@link ContextConfiguration} annotation and
198
+ * declaring class and then adding the attributes to the supplied list.
198
199
*/
199
200
private static void convertContextConfigToConfigAttributesAndAddToList (ContextConfiguration contextConfiguration ,
200
201
Class <?> declaringClass , final List <ContextConfigurationAttributes > attributesList ) {
@@ -211,6 +212,27 @@ private static void convertContextConfigToConfigAttributesAndAddToList(ContextCo
211
212
attributesList .add (attributes );
212
213
}
213
214
215
+ /**
216
+ * Convenience method for creating a {@link ContextConfigurationAttributes}
217
+ * instance from the supplied {@link AnnotationAttributes} and declaring
218
+ * class and then adding the attributes to the supplied list.
219
+ *
220
+ * @since 4.0
221
+ */
222
+ private static void convertAnnotationAttributesToConfigAttributesAndAddToList (AnnotationAttributes annAttrs ,
223
+ Class <?> declaringClass , final List <ContextConfigurationAttributes > attributesList ) {
224
+ if (logger .isTraceEnabled ()) {
225
+ logger .trace (String .format ("Retrieved @ContextConfiguration attributes [%s] for declaring class [%s]." ,
226
+ annAttrs , declaringClass .getName ()));
227
+ }
228
+
229
+ ContextConfigurationAttributes attributes = new ContextConfigurationAttributes (declaringClass , annAttrs );
230
+ if (logger .isTraceEnabled ()) {
231
+ logger .trace ("Resolved context configuration attributes: " + attributes );
232
+ }
233
+ attributesList .add (attributes );
234
+ }
235
+
214
236
/**
215
237
* Resolve the list of lists of {@linkplain ContextConfigurationAttributes context
216
238
* configuration attributes} for the supplied {@linkplain Class test class} and its
@@ -243,6 +265,8 @@ private static void convertContextConfigToConfigAttributesAndAddToList(ContextCo
243
265
* <em>present</em> on the supplied class; or if a given class in the class hierarchy
244
266
* declares both {@code @ContextConfiguration} and {@code @ContextHierarchy} as
245
267
* top-level annotations.
268
+ * @throws IllegalStateException if no class in the class hierarchy declares
269
+ * {@code @ContextHierarchy}.
246
270
*
247
271
* @since 3.2.2
248
272
* @see #buildContextHierarchyMap(Class)
@@ -251,6 +275,7 @@ private static void convertContextConfigToConfigAttributesAndAddToList(ContextCo
251
275
@ SuppressWarnings ("unchecked" )
252
276
static List <List <ContextConfigurationAttributes >> resolveContextHierarchyAttributes (Class <?> testClass ) {
253
277
Assert .notNull (testClass , "Class must not be null" );
278
+ Assert .state (findAnnotation (testClass , ContextHierarchy .class ) != null , "@ContextHierarchy must be present" );
254
279
255
280
final Class <ContextConfiguration > contextConfigType = ContextConfiguration .class ;
256
281
final Class <ContextHierarchy > contextHierarchyType = ContextHierarchy .class ;
@@ -263,27 +288,25 @@ static List<List<ContextConfigurationAttributes>> resolveContextHierarchyAttribu
263
288
contextConfigType .getName (), contextHierarchyType .getName (), testClass .getName ()));
264
289
265
290
while (descriptor != null ) {
266
- Class <?> rootDeclaringClass = descriptor .getDeclaringClass ();
267
- Class <?> declaringClass = (descriptor .getStereotype () != null ) ? descriptor .getStereotypeType ()
268
- : rootDeclaringClass ;
291
+ Class <?> rootDeclaringClass = descriptor .getRootDeclaringClass ();
292
+ Class <?> declaringClass = descriptor .getDeclaringClass ();
269
293
270
294
boolean contextConfigDeclaredLocally = isAnnotationDeclaredLocally (contextConfigType , declaringClass );
271
295
boolean contextHierarchyDeclaredLocally = isAnnotationDeclaredLocally (contextHierarchyType , declaringClass );
272
296
273
297
if (contextConfigDeclaredLocally && contextHierarchyDeclaredLocally ) {
274
- String msg = String .format ("Test class [%s] has been configured with both @ContextConfiguration "
298
+ String msg = String .format ("Class [%s] has been configured with both @ContextConfiguration "
275
299
+ "and @ContextHierarchy. Only one of these annotations may be declared on a test class "
276
- + "or custom stereotype annotation." , rootDeclaringClass .getName ());
300
+ + "or custom stereotype annotation." , declaringClass .getName ());
277
301
logger .error (msg );
278
302
throw new IllegalStateException (msg );
279
303
}
280
304
281
305
final List <ContextConfigurationAttributes > configAttributesList = new ArrayList <ContextConfigurationAttributes >();
282
306
283
307
if (contextConfigDeclaredLocally ) {
284
- ContextConfiguration contextConfiguration = getAnnotation (declaringClass , contextConfigType );
285
- convertContextConfigToConfigAttributesAndAddToList (contextConfiguration , declaringClass ,
286
- configAttributesList );
308
+ convertAnnotationAttributesToConfigAttributesAndAddToList (descriptor .getAnnotationAttributes (),
309
+ declaringClass , configAttributesList );
287
310
}
288
311
else if (contextHierarchyDeclaredLocally ) {
289
312
ContextHierarchy contextHierarchy = getAnnotation (declaringClass , contextHierarchyType );
@@ -293,7 +316,7 @@ else if (contextHierarchyDeclaredLocally) {
293
316
}
294
317
}
295
318
else {
296
- // This should theoretically actually never happen...
319
+ // This should theoretically never happen...
297
320
String msg = String .format ("Test class [%s] has been configured with neither @ContextConfiguration "
298
321
+ "nor @ContextHierarchy as a class-level annotation." , rootDeclaringClass .getName ());
299
322
logger .error (msg );
@@ -405,13 +428,9 @@ static List<ContextConfigurationAttributes> resolveContextConfigurationAttribute
405
428
annotationType .getName (), testClass .getName ()));
406
429
407
430
while (descriptor != null ) {
408
- Class <?> rootDeclaringClass = descriptor .getDeclaringClass ();
409
- Class <?> declaringClass = (descriptor .getStereotype () != null ) ? descriptor .getStereotypeType ()
410
- : rootDeclaringClass ;
411
-
412
- convertContextConfigToConfigAttributesAndAddToList (descriptor .getAnnotation (), declaringClass ,
413
- attributesList );
414
- descriptor = findAnnotationDescriptor (rootDeclaringClass .getSuperclass (), annotationType );
431
+ convertAnnotationAttributesToConfigAttributesAndAddToList (descriptor .getAnnotationAttributes (),
432
+ descriptor .getDeclaringClass (), attributesList );
433
+ descriptor = findAnnotationDescriptor (descriptor .getRootDeclaringClass ().getSuperclass (), annotationType );
415
434
}
416
435
417
436
return attributesList ;
@@ -489,20 +508,18 @@ static String[] resolveActiveProfiles(Class<?> testClass) {
489
508
final Set <String > activeProfiles = new HashSet <String >();
490
509
491
510
while (descriptor != null ) {
492
- Class <?> rootDeclaringClass = descriptor .getDeclaringClass ();
493
- Class <?> declaringClass = (descriptor .getStereotype () != null ) ? descriptor .getStereotypeType ()
494
- : rootDeclaringClass ;
511
+ Class <?> declaringClass = descriptor .getDeclaringClass ();
495
512
496
- ActiveProfiles annotation = descriptor .getAnnotation ();
513
+ AnnotationAttributes annAttrs = descriptor .getAnnotationAttributes ();
497
514
if (logger .isTraceEnabled ()) {
498
- logger .trace (String .format ("Retrieved @ActiveProfiles [%s] for declaring class [%s]." , annotation ,
499
- declaringClass .getName ()));
515
+ logger .trace (String .format ("Retrieved @ActiveProfiles attributes [%s] for declaring class [%s]." ,
516
+ annAttrs , declaringClass .getName ()));
500
517
}
501
- validateActiveProfilesConfiguration (declaringClass , annotation );
518
+ validateActiveProfilesConfiguration (declaringClass , annAttrs );
502
519
503
- String [] profiles = annotation . profiles ( );
504
- String [] valueProfiles = annotation . value ( );
505
- Class <? extends ActiveProfilesResolver > resolverClass = annotation . resolver ( );
520
+ String [] profiles = annAttrs . getStringArray ( "profiles" );
521
+ String [] valueProfiles = annAttrs . getStringArray ( "value" );
522
+ Class <? extends ActiveProfilesResolver > resolverClass = annAttrs . getClass ( "resolver" );
506
523
507
524
boolean resolverDeclared = !ActiveProfilesResolver .class .equals (resolverClass );
508
525
boolean valueDeclared = !ObjectUtils .isEmpty (valueProfiles );
@@ -538,17 +555,17 @@ else if (valueDeclared) {
538
555
}
539
556
}
540
557
541
- descriptor = annotation . inheritProfiles ( ) ? findAnnotationDescriptor (rootDeclaringClass . getSuperclass (),
542
- annotationType ) : null ;
558
+ descriptor = annAttrs . getBoolean ( "inheritProfiles" ) ? findAnnotationDescriptor (
559
+ descriptor . getRootDeclaringClass (). getSuperclass (), annotationType ) : null ;
543
560
}
544
561
545
562
return StringUtils .toStringArray (activeProfiles );
546
563
}
547
564
548
- private static void validateActiveProfilesConfiguration (Class <?> declaringClass , ActiveProfiles annotation ) {
549
- String [] valueProfiles = annotation . value ( );
550
- String [] profiles = annotation . profiles ( );
551
- Class <? extends ActiveProfilesResolver > resolverClass = annotation . resolver ( );
565
+ private static void validateActiveProfilesConfiguration (Class <?> declaringClass , AnnotationAttributes annAttrs ) {
566
+ String [] valueProfiles = annAttrs . getStringArray ( "value" );
567
+ String [] profiles = annAttrs . getStringArray ( "profiles" );
568
+ Class <? extends ActiveProfilesResolver > resolverClass = annAttrs . getClass ( "resolver" );
552
569
boolean valueDeclared = !ObjectUtils .isEmpty (valueProfiles );
553
570
boolean profilesDeclared = !ObjectUtils .isEmpty (profiles );
554
571
boolean resolverDeclared = !ActiveProfilesResolver .class .equals (resolverClass );
0 commit comments