1
1
/*
2
- * Copyright 2002-2015 the original author or authors.
2
+ * Copyright 2002-2016 the original author or authors.
3
3
*
4
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
5
* you may not use this file except in compliance with the License.
18
18
19
19
import java .util .ArrayList ;
20
20
import java .util .Arrays ;
21
+ import java .util .Collection ;
21
22
import java .util .Collections ;
22
23
import java .util .HashSet ;
23
24
import java .util .LinkedHashSet ;
30
31
31
32
import org .springframework .beans .BeanInstantiationException ;
32
33
import org .springframework .beans .BeanUtils ;
33
- import org .springframework .context .ApplicationContextInitializer ;
34
- import org .springframework .context .ConfigurableApplicationContext ;
35
34
import org .springframework .core .annotation .AnnotationAwareOrderComparator ;
36
35
import org .springframework .core .annotation .AnnotationUtils ;
37
36
import org .springframework .core .io .support .SpringFactoriesLoader ;
71
70
*
72
71
* @author Sam Brannen
73
72
* @author Juergen Hoeller
73
+ * @author Phillip Webb
74
74
* @since 4.1
75
75
*/
76
76
public abstract class AbstractTestContextBootstrapper implements TestContextBootstrapper {
@@ -272,13 +272,8 @@ public final MergedContextConfiguration buildMergedContextConfiguration() {
272
272
CacheAwareContextLoaderDelegate cacheAwareContextLoaderDelegate = getCacheAwareContextLoaderDelegate ();
273
273
274
274
if (MetaAnnotationUtils .findAnnotationDescriptorForTypes (testClass , ContextConfiguration .class ,
275
- ContextHierarchy .class ) == null ) {
276
- if (logger .isInfoEnabled ()) {
277
- logger .info (String .format (
278
- "Neither @ContextConfiguration nor @ContextHierarchy found for test class [%s]" ,
279
- testClass .getName ()));
280
- }
281
- return new MergedContextConfiguration (testClass , null , null , null , null );
275
+ ContextHierarchy .class ) == null ) {
276
+ return buildDefaultMergedContextConfiguration (testClass , cacheAwareContextLoaderDelegate );
282
277
}
283
278
284
279
if (AnnotationUtils .findAnnotation (testClass , ContextHierarchy .class ) != null ) {
@@ -297,7 +292,7 @@ public final MergedContextConfiguration buildMergedContextConfiguration() {
297
292
Class <?> declaringClass = reversedList .get (0 ).getDeclaringClass ();
298
293
299
294
mergedConfig = buildMergedContextConfiguration (declaringClass , reversedList , parentConfig ,
300
- cacheAwareContextLoaderDelegate );
295
+ cacheAwareContextLoaderDelegate , true );
301
296
parentConfig = mergedConfig ;
302
297
}
303
298
@@ -307,10 +302,29 @@ public final MergedContextConfiguration buildMergedContextConfiguration() {
307
302
else {
308
303
return buildMergedContextConfiguration (testClass ,
309
304
ContextLoaderUtils .resolveContextConfigurationAttributes (testClass ), null ,
310
- cacheAwareContextLoaderDelegate );
305
+ cacheAwareContextLoaderDelegate , true );
311
306
}
312
307
}
313
308
309
+ /**
310
+ * @since 4.3
311
+ */
312
+ private MergedContextConfiguration buildDefaultMergedContextConfiguration (Class <?> testClass ,
313
+ CacheAwareContextLoaderDelegate cacheAwareContextLoaderDelegate ) {
314
+
315
+ List <ContextConfigurationAttributes > defaultConfigAttributesList
316
+ = Collections .singletonList (new ContextConfigurationAttributes (testClass ));
317
+
318
+ ContextLoader contextLoader = resolveContextLoader (testClass , defaultConfigAttributesList );
319
+ if (logger .isInfoEnabled ()) {
320
+ logger .info (String .format (
321
+ "Neither @ContextConfiguration nor @ContextHierarchy found for test class [%s], using %s" ,
322
+ testClass .getName (), contextLoader .getClass ().getSimpleName ()));
323
+ }
324
+ return buildMergedContextConfiguration (testClass , defaultConfigAttributesList , null ,
325
+ cacheAwareContextLoaderDelegate , false );
326
+ }
327
+
314
328
/**
315
329
* Build the {@link MergedContextConfiguration merged context configuration}
316
330
* for the supplied {@link Class testClass}, context configuration attributes,
@@ -324,6 +338,9 @@ public final MergedContextConfiguration buildMergedContextConfiguration() {
324
338
* context in a context hierarchy, or {@code null} if there is no parent
325
339
* @param cacheAwareContextLoaderDelegate the cache-aware context loader delegate to
326
340
* be passed to the {@code MergedContextConfiguration} constructor
341
+ * @param requireLocationsClassesOrInitializers whether locations, classes, or
342
+ * initializers are required; typically {@code true} but may be set to {@code false}
343
+ * if the configured loader supports empty configuration
327
344
* @return the merged context configuration
328
345
* @see #resolveContextLoader
329
346
* @see ContextLoaderUtils#resolveContextConfigurationAttributes
@@ -335,11 +352,15 @@ public final MergedContextConfiguration buildMergedContextConfiguration() {
335
352
*/
336
353
private MergedContextConfiguration buildMergedContextConfiguration (Class <?> testClass ,
337
354
List <ContextConfigurationAttributes > configAttributesList , MergedContextConfiguration parentConfig ,
338
- CacheAwareContextLoaderDelegate cacheAwareContextLoaderDelegate ) {
355
+ CacheAwareContextLoaderDelegate cacheAwareContextLoaderDelegate ,
356
+ boolean requireLocationsClassesOrInitializers ) {
357
+
358
+ Assert .notEmpty (configAttributesList , "ContextConfigurationAttributes list must not be null or empty" );
339
359
340
360
ContextLoader contextLoader = resolveContextLoader (testClass , configAttributesList );
341
- List <String > locationsList = new ArrayList <String >();
342
- List <Class <?>> classesList = new ArrayList <Class <?>>();
361
+ List <String > locations = new ArrayList <String >();
362
+ List <Class <?>> classes = new ArrayList <Class <?>>();
363
+ List <Class <?>> initializers = new ArrayList <Class <?>>();
343
364
344
365
for (ContextConfigurationAttributes configAttributes : configAttributesList ) {
345
366
if (logger .isTraceEnabled ()) {
@@ -349,34 +370,53 @@ private MergedContextConfiguration buildMergedContextConfiguration(Class<?> test
349
370
if (contextLoader instanceof SmartContextLoader ) {
350
371
SmartContextLoader smartContextLoader = (SmartContextLoader ) contextLoader ;
351
372
smartContextLoader .processContextConfiguration (configAttributes );
352
- locationsList .addAll (0 , Arrays .asList (configAttributes .getLocations ()));
353
- classesList .addAll (0 , Arrays .asList (configAttributes .getClasses ()));
373
+ locations .addAll (0 , Arrays .asList (configAttributes .getLocations ()));
374
+ classes .addAll (0 , Arrays .asList (configAttributes .getClasses ()));
354
375
}
355
376
else {
356
- String [] processedLocations = contextLoader .processLocations (configAttributes . getDeclaringClass (),
357
- configAttributes .getLocations ());
358
- locationsList .addAll (0 , Arrays .asList (processedLocations ));
377
+ String [] processedLocations = contextLoader .processLocations (
378
+ configAttributes . getDeclaringClass (), configAttributes .getLocations ());
379
+ locations .addAll (0 , Arrays .asList (processedLocations ));
359
380
// Legacy ContextLoaders don't know how to process classes
360
381
}
382
+ initializers .addAll (0 , Arrays .asList (configAttributes .getInitializers ()));
361
383
if (!configAttributes .isInheritLocations ()) {
362
384
break ;
363
385
}
364
386
}
365
387
366
- String [] locations = StringUtils . toStringArray ( locationsList );
367
- Class <?>[] classes = ClassUtils . toClassArray ( classesList );
368
- Set < Class <? extends ApplicationContextInitializer <? extends ConfigurableApplicationContext >>> initializerClasses = //
369
- ApplicationContextInitializerUtils . resolveInitializerClasses ( configAttributesList );
370
- String [] activeProfiles = ActiveProfilesUtils . resolveActiveProfiles ( testClass );
371
- MergedTestPropertySources mergedTestPropertySources = TestPropertySourceUtils . buildMergedTestPropertySources ( testClass );
388
+ if ( requireLocationsClassesOrInitializers && areAllEmpty ( locations , classes , initializers )) {
389
+ throw new IllegalStateException ( String . format (
390
+ "%s was unable to detect defaults, and no ApplicationContextInitializers "
391
+ + "were declared for context configuration attributes %s" ,
392
+ contextLoader . getClass (). getSimpleName (), configAttributesList ) );
393
+ }
372
394
373
- MergedContextConfiguration mergedConfig = new MergedContextConfiguration (testClass , locations , classes ,
374
- initializerClasses , activeProfiles , mergedTestPropertySources .getLocations (),
375
- mergedTestPropertySources .getProperties (), contextLoader , cacheAwareContextLoaderDelegate , parentConfig );
395
+ MergedTestPropertySources mergedTestPropertySources = TestPropertySourceUtils .buildMergedTestPropertySources (testClass );
396
+ MergedContextConfiguration mergedConfig = new MergedContextConfiguration (testClass ,
397
+ StringUtils .toStringArray (locations ),
398
+ ClassUtils .toClassArray (classes ),
399
+ ApplicationContextInitializerUtils .resolveInitializerClasses (configAttributesList ),
400
+ ActiveProfilesUtils .resolveActiveProfiles (testClass ),
401
+ mergedTestPropertySources .getLocations (),
402
+ mergedTestPropertySources .getProperties (),
403
+ contextLoader , cacheAwareContextLoaderDelegate , parentConfig );
376
404
377
405
return processMergedContextConfiguration (mergedConfig );
378
406
}
379
407
408
+ /**
409
+ * @since 4.3
410
+ */
411
+ private boolean areAllEmpty (Collection <?>... collections ) {
412
+ for (Collection <?> collection : collections ) {
413
+ if (!collection .isEmpty ()) {
414
+ return false ;
415
+ }
416
+ }
417
+ return true ;
418
+ }
419
+
380
420
/**
381
421
* Resolve the {@link ContextLoader} {@linkplain Class class} to use for the
382
422
* supplied list of {@link ContextConfigurationAttributes} and then instantiate
@@ -389,7 +429,7 @@ private MergedContextConfiguration buildMergedContextConfiguration(Class<?> test
389
429
* @param testClass the test class for which the {@code ContextLoader} should be
390
430
* resolved; must not be {@code null}
391
431
* @param configAttributesList the list of configuration attributes to process; must
392
- * not be {@code null} or <em>empty</em> ; must be ordered <em>bottom-up</em>
432
+ * not be {@code null}; must be ordered <em>bottom-up</em>
393
433
* (i.e., as if we were traversing up the class hierarchy)
394
434
* @return the resolved {@code ContextLoader} for the supplied {@code testClass}
395
435
* (never {@code null})
@@ -400,7 +440,7 @@ protected ContextLoader resolveContextLoader(Class<?> testClass,
400
440
List <ContextConfigurationAttributes > configAttributesList ) {
401
441
402
442
Assert .notNull (testClass , "Class must not be null" );
403
- Assert .notEmpty (configAttributesList , "ContextConfigurationAttributes list must not be empty " );
443
+ Assert .notNull (configAttributesList , "ContextConfigurationAttributes list must not be null " );
404
444
405
445
Class <? extends ContextLoader > contextLoaderClass = resolveExplicitContextLoaderClass (configAttributesList );
406
446
if (contextLoaderClass == null ) {
@@ -429,7 +469,7 @@ protected ContextLoader resolveContextLoader(Class<?> testClass,
429
469
* step #1.</li>
430
470
* </ol>
431
471
* @param configAttributesList the list of configuration attributes to process;
432
- * must not be {@code null} or <em>empty</em> ; must be ordered <em>bottom-up</em>
472
+ * must not be {@code null}; must be ordered <em>bottom-up</em>
433
473
* (i.e., as if we were traversing up the class hierarchy)
434
474
* @return the {@code ContextLoader} class to use for the supplied configuration
435
475
* attributes, or {@code null} if no explicit loader is found
@@ -439,7 +479,8 @@ protected ContextLoader resolveContextLoader(Class<?> testClass,
439
479
protected Class <? extends ContextLoader > resolveExplicitContextLoaderClass (
440
480
List <ContextConfigurationAttributes > configAttributesList ) {
441
481
442
- Assert .notEmpty (configAttributesList , "ContextConfigurationAttributes list must not be empty" );
482
+ Assert .notNull (configAttributesList , "ContextConfigurationAttributes list must not be null" );
483
+
443
484
for (ContextConfigurationAttributes configAttributes : configAttributesList ) {
444
485
if (logger .isTraceEnabled ()) {
445
486
logger .trace (String .format ("Resolving ContextLoader for context configuration attributes %s" ,
0 commit comments