Search in sources :

Example 1 with ContextHierarchy

use of cn.taketoday.test.context.ContextHierarchy in project today-framework by TAKETODAY.

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.
 * @see #buildContextHierarchyMap(Class)
 * @see #resolveContextConfigurationAttributes(Class)
 * @since 4.0
 */
@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 = (ContextConfiguration) desc.getAnnotation();
            convertContextConfigToConfigAttributesAndAddToList(contextConfiguration, rootDeclaringClass, configAttributesList);
        } else if (contextHierarchyDeclaredLocally) {
            ContextHierarchy contextHierarchy = getAnnotation(declaringClass, contextHierarchyType);
            if (contextHierarchy != null) {
                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 = desc.next();
    }
    return hierarchyAttributes;
}
Also used : ContextConfigurationAttributes(cn.taketoday.test.context.ContextConfigurationAttributes) ArrayList(java.util.ArrayList) UntypedAnnotationDescriptor(cn.taketoday.test.context.TestContextAnnotationUtils.UntypedAnnotationDescriptor) ContextHierarchy(cn.taketoday.test.context.ContextHierarchy) ArrayList(java.util.ArrayList) List(java.util.List) ContextConfiguration(cn.taketoday.test.context.ContextConfiguration)

Example 2 with ContextHierarchy

use of cn.taketoday.test.context.ContextHierarchy in project today-framework by TAKETODAY.

the class ApplicationTestContextBootstrapper method isWebEnvironmentSupported.

private boolean isWebEnvironmentSupported(MergedContextConfiguration mergedConfig) {
    Class<?> testClass = mergedConfig.getTestClass();
    ContextHierarchy hierarchy = AnnotationUtils.getAnnotation(testClass, ContextHierarchy.class);
    if (hierarchy == null || hierarchy.value().length == 0) {
        return true;
    }
    ContextConfiguration[] configurations = hierarchy.value();
    return isFromConfiguration(mergedConfig, configurations[configurations.length - 1]);
}
Also used : ContextHierarchy(cn.taketoday.test.context.ContextHierarchy) MergedContextConfiguration(cn.taketoday.test.context.MergedContextConfiguration) ContextConfiguration(cn.taketoday.test.context.ContextConfiguration) WebMergedContextConfiguration(cn.taketoday.test.context.web.WebMergedContextConfiguration)

Example 3 with ContextHierarchy

use of cn.taketoday.test.context.ContextHierarchy in project today-infrastructure by TAKETODAY.

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.
 * @see #buildContextHierarchyMap(Class)
 * @see #resolveContextConfigurationAttributes(Class)
 * @since 4.0
 */
@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 = (ContextConfiguration) desc.getAnnotation();
            convertContextConfigToConfigAttributesAndAddToList(contextConfiguration, rootDeclaringClass, configAttributesList);
        } else if (contextHierarchyDeclaredLocally) {
            ContextHierarchy contextHierarchy = getAnnotation(declaringClass, contextHierarchyType);
            if (contextHierarchy != null) {
                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 = desc.next();
    }
    return hierarchyAttributes;
}
Also used : ContextConfigurationAttributes(cn.taketoday.test.context.ContextConfigurationAttributes) ArrayList(java.util.ArrayList) UntypedAnnotationDescriptor(cn.taketoday.test.context.TestContextAnnotationUtils.UntypedAnnotationDescriptor) ContextHierarchy(cn.taketoday.test.context.ContextHierarchy) ArrayList(java.util.ArrayList) List(java.util.List) ContextConfiguration(cn.taketoday.test.context.ContextConfiguration)

Example 4 with ContextHierarchy

use of cn.taketoday.test.context.ContextHierarchy in project today-infrastructure by TAKETODAY.

the class ApplicationTestContextBootstrapper method isWebEnvironmentSupported.

private boolean isWebEnvironmentSupported(MergedContextConfiguration mergedConfig) {
    Class<?> testClass = mergedConfig.getTestClass();
    ContextHierarchy hierarchy = AnnotationUtils.getAnnotation(testClass, ContextHierarchy.class);
    if (hierarchy == null || hierarchy.value().length == 0) {
        return true;
    }
    ContextConfiguration[] configurations = hierarchy.value();
    return isFromConfiguration(mergedConfig, configurations[configurations.length - 1]);
}
Also used : ContextHierarchy(cn.taketoday.test.context.ContextHierarchy) MergedContextConfiguration(cn.taketoday.test.context.MergedContextConfiguration) ContextConfiguration(cn.taketoday.test.context.ContextConfiguration) WebMergedContextConfiguration(cn.taketoday.test.context.web.WebMergedContextConfiguration)

Aggregations

ContextConfiguration (cn.taketoday.test.context.ContextConfiguration)4 ContextHierarchy (cn.taketoday.test.context.ContextHierarchy)4 ContextConfigurationAttributes (cn.taketoday.test.context.ContextConfigurationAttributes)2 MergedContextConfiguration (cn.taketoday.test.context.MergedContextConfiguration)2 UntypedAnnotationDescriptor (cn.taketoday.test.context.TestContextAnnotationUtils.UntypedAnnotationDescriptor)2 WebMergedContextConfiguration (cn.taketoday.test.context.web.WebMergedContextConfiguration)2 ArrayList (java.util.ArrayList)2 List (java.util.List)2