Search in sources :

Example 11 with ContextConfigurationAttributes

use of org.springframework.test.context.ContextConfigurationAttributes in project spring-framework by spring-projects.

the class ContextLoaderUtils method resolveContextHierarchyAttributes.

/**
	 * Resolve the list of lists of {@linkplain ContextConfigurationAttributes context
	 * configuration attributes} for the supplied {@linkplain Class test class} and its
	 * superclasses, taking into account context hierarchies declared via
	 * {@link ContextHierarchy @ContextHierarchy} and
	 * {@link ContextConfiguration @ContextConfiguration}.
	 * <p>The outer list represents a top-down ordering of context configuration
	 * attributes, where each element in the list represents the context configuration
	 * declared on a given test class in the class hierarchy. Each nested list
	 * contains the context configuration attributes declared either via a single
	 * instance of {@code @ContextConfiguration} on the particular class or via
	 * multiple instances of {@code @ContextConfiguration} declared within a
	 * single {@code @ContextHierarchy} instance on the particular class.
	 * Furthermore, each nested list maintains the order in which
	 * {@code @ContextConfiguration} instances are declared.
	 * <p>Note that the {@link ContextConfiguration#inheritLocations inheritLocations} and
	 * {@link ContextConfiguration#inheritInitializers() inheritInitializers} flags of
	 * {@link ContextConfiguration @ContextConfiguration} will <strong>not</strong>
	 * be taken into consideration. If these flags need to be honored, that must be
	 * handled manually when traversing the nested lists returned by this method.
	 * @param testClass the class for which to resolve the context hierarchy attributes
	 * (must not be {@code null})
	 * @return the list of lists of configuration attributes for the specified class;
	 * never {@code null}
	 * @throws IllegalArgumentException if the supplied class is {@code null}; or if
	 * neither {@code @ContextConfiguration} nor {@code @ContextHierarchy} is
	 * <em>present</em> on the supplied class
	 * @throws IllegalStateException if a test class or composed annotation
	 * in the class hierarchy declares both {@code @ContextConfiguration} and
	 * {@code @ContextHierarchy} as top-level annotations.
	 * @since 3.2.2
	 * @see #buildContextHierarchyMap(Class)
	 * @see #resolveContextConfigurationAttributes(Class)
	 */
@SuppressWarnings("unchecked")
static List<List<ContextConfigurationAttributes>> resolveContextHierarchyAttributes(Class<?> testClass) {
    Assert.notNull(testClass, "Class must not be null");
    Class<ContextConfiguration> contextConfigType = ContextConfiguration.class;
    Class<ContextHierarchy> contextHierarchyType = ContextHierarchy.class;
    List<List<ContextConfigurationAttributes>> hierarchyAttributes = new ArrayList<>();
    UntypedAnnotationDescriptor desc = findAnnotationDescriptorForTypes(testClass, contextConfigType, contextHierarchyType);
    Assert.notNull(desc, () -> String.format("Could not find an 'annotation declaring class' for annotation type [%s] or [%s] and test class [%s]", contextConfigType.getName(), contextHierarchyType.getName(), testClass.getName()));
    while (desc != null) {
        Class<?> rootDeclaringClass = desc.getRootDeclaringClass();
        Class<?> declaringClass = desc.getDeclaringClass();
        boolean contextConfigDeclaredLocally = isAnnotationDeclaredLocally(contextConfigType, declaringClass);
        boolean contextHierarchyDeclaredLocally = isAnnotationDeclaredLocally(contextHierarchyType, declaringClass);
        if (contextConfigDeclaredLocally && contextHierarchyDeclaredLocally) {
            String msg = String.format("Class [%s] has been configured with both @ContextConfiguration " + "and @ContextHierarchy. Only one of these annotations may be declared on a test class " + "or composed annotation.", declaringClass.getName());
            logger.error(msg);
            throw new IllegalStateException(msg);
        }
        List<ContextConfigurationAttributes> configAttributesList = new ArrayList<>();
        if (contextConfigDeclaredLocally) {
            ContextConfiguration contextConfiguration = AnnotationUtils.synthesizeAnnotation(desc.getAnnotationAttributes(), ContextConfiguration.class, desc.getRootDeclaringClass());
            convertContextConfigToConfigAttributesAndAddToList(contextConfiguration, rootDeclaringClass, configAttributesList);
        } else if (contextHierarchyDeclaredLocally) {
            ContextHierarchy contextHierarchy = getAnnotation(declaringClass, contextHierarchyType);
            for (ContextConfiguration contextConfiguration : contextHierarchy.value()) {
                convertContextConfigToConfigAttributesAndAddToList(contextConfiguration, rootDeclaringClass, configAttributesList);
            }
        } else {
            // This should theoretically never happen...
            String msg = String.format("Test class [%s] has been configured with neither @ContextConfiguration " + "nor @ContextHierarchy as a class-level annotation.", rootDeclaringClass.getName());
            logger.error(msg);
            throw new IllegalStateException(msg);
        }
        hierarchyAttributes.add(0, configAttributesList);
        desc = findAnnotationDescriptorForTypes(rootDeclaringClass.getSuperclass(), contextConfigType, contextHierarchyType);
    }
    return hierarchyAttributes;
}
Also used : ContextConfigurationAttributes(org.springframework.test.context.ContextConfigurationAttributes) ArrayList(java.util.ArrayList) ContextHierarchy(org.springframework.test.context.ContextHierarchy) ArrayList(java.util.ArrayList) List(java.util.List) ContextConfiguration(org.springframework.test.context.ContextConfiguration)

Example 12 with ContextConfigurationAttributes

use of org.springframework.test.context.ContextConfigurationAttributes in project spring-framework by spring-projects.

the class ContextLoaderUtils method buildContextHierarchyMap.

/**
	 * Build a <em>context hierarchy map</em> for the supplied {@linkplain Class
	 * test class} and its superclasses, taking into account context hierarchies
	 * declared via {@link ContextHierarchy @ContextHierarchy} and
	 * {@link ContextConfiguration @ContextConfiguration}.
	 * <p>Each value in the map represents the consolidated list of {@linkplain
	 * ContextConfigurationAttributes context configuration attributes} for a
	 * given level in the context hierarchy (potentially across the test class
	 * hierarchy), keyed by the {@link ContextConfiguration#name() name} of the
	 * context hierarchy level.
	 * <p>If a given level in the context hierarchy does not have an explicit
	 * name (i.e., configured via {@link ContextConfiguration#name}), a name will
	 * be generated for that hierarchy level by appending the numerical level to
	 * the {@link #GENERATED_CONTEXT_HIERARCHY_LEVEL_PREFIX}.
	 * @param testClass the class for which to resolve the context hierarchy map
	 * (must not be {@code null})
	 * @return a map of context configuration attributes for the context hierarchy,
	 * keyed by context hierarchy level name; never {@code null}
	 * @throws IllegalArgumentException if the lists of context configuration
	 * attributes for each level in the {@code @ContextHierarchy} do not define
	 * unique context configuration within the overall hierarchy.
	 * @since 3.2.2
	 * @see #resolveContextHierarchyAttributes(Class)
	 */
static Map<String, List<ContextConfigurationAttributes>> buildContextHierarchyMap(Class<?> testClass) {
    final Map<String, List<ContextConfigurationAttributes>> map = new LinkedHashMap<>();
    int hierarchyLevel = 1;
    for (List<ContextConfigurationAttributes> configAttributesList : resolveContextHierarchyAttributes(testClass)) {
        for (ContextConfigurationAttributes configAttributes : configAttributesList) {
            String name = configAttributes.getName();
            // Assign a generated name?
            if (!StringUtils.hasText(name)) {
                name = GENERATED_CONTEXT_HIERARCHY_LEVEL_PREFIX + hierarchyLevel;
            }
            // Encountered a new context hierarchy level?
            if (!map.containsKey(name)) {
                hierarchyLevel++;
                map.put(name, new ArrayList<>());
            }
            map.get(name).add(configAttributes);
        }
    }
    // Check for uniqueness
    Set<List<ContextConfigurationAttributes>> set = new HashSet<>(map.values());
    if (set.size() != map.size()) {
        String msg = String.format("The @ContextConfiguration elements configured via @ContextHierarchy in " + "test class [%s] and its superclasses must define unique contexts per hierarchy level.", testClass.getName());
        logger.error(msg);
        throw new IllegalStateException(msg);
    }
    return map;
}
Also used : ContextConfigurationAttributes(org.springframework.test.context.ContextConfigurationAttributes) ArrayList(java.util.ArrayList) List(java.util.List) LinkedHashMap(java.util.LinkedHashMap) HashSet(java.util.HashSet)

Aggregations

ContextConfigurationAttributes (org.springframework.test.context.ContextConfigurationAttributes)12 Test (org.junit.Test)5 ArrayList (java.util.ArrayList)4 List (java.util.List)3 HashSet (java.util.HashSet)2 ContextConfiguration (org.springframework.test.context.ContextConfiguration)2 ContextHierarchy (org.springframework.test.context.ContextHierarchy)2 ContextLoader (org.springframework.test.context.ContextLoader)2 MergedContextConfiguration (org.springframework.test.context.MergedContextConfiguration)2 SmartContextLoader (org.springframework.test.context.SmartContextLoader)2 LinkedHashMap (java.util.LinkedHashMap)1 ApplicationContextInitializer (org.springframework.context.ApplicationContextInitializer)1 ConfigurableApplicationContext (org.springframework.context.ConfigurableApplicationContext)1 CacheAwareContextLoaderDelegate (org.springframework.test.context.CacheAwareContextLoaderDelegate)1 ContextCustomizer (org.springframework.test.context.ContextCustomizer)1