Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce getMergedAnnotation() in TestContextAnnotationUtils #34456

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@
* example, {@link ContextConfiguration#inheritLocations}.
*
* @author Sam Brannen
* @author Yanming Zhou
* @since 5.3
* @see MergedAnnotations
* @see MergedAnnotations.Search
Expand Down Expand Up @@ -135,11 +136,39 @@ public static boolean hasAnnotation(Class<?> clazz, Class<? extends Annotation>
private static <T extends Annotation> @Nullable T findMergedAnnotation(Class<?> clazz, Class<T> annotationType,
Predicate<Class<?>> searchEnclosingClass) {

return getMergedAnnotation(clazz, annotationType, searchEnclosingClass)
.synthesize(MergedAnnotation::isPresent).orElse(null);
}

/**
* Get the {@link MergedAnnotation} of the specified {@code annotationType} within
* the annotation hierarchy <em>above</em> the supplied class.
* <p>In the context of this method, the term "above" means within the
* {@linkplain Class#getSuperclass() superclass} hierarchy or within the
* {@linkplain Class#getEnclosingClass() enclosing class} hierarchy of the
* supplied class. The enclosing class hierarchy will only be searched
* according to {@link NestedTestConfiguration @NestedTestConfiguration}
* semantics.
* <p>{@link org.springframework.core.annotation.AliasFor @AliasFor} semantics
* are fully supported, both within a single annotation and within annotation
* hierarchies.
* @param clazz the class to look for annotations on
* @param annotationType the type of annotation to look for
* @return a {@link MergedAnnotation} instance
* @see #findMergedAnnotation(Class, Class)
* @see #searchEnclosingClass(Class)
*/
public static <T extends Annotation> MergedAnnotation<T> getMergedAnnotation(Class<?> clazz, Class<T> annotationType) {
return getMergedAnnotation(clazz, annotationType, TestContextAnnotationUtils::searchEnclosingClass);
}

private static <T extends Annotation> MergedAnnotation<T> getMergedAnnotation(Class<?> clazz, Class<T> annotationType,
Predicate<Class<?>> searchEnclosingClass) {

return MergedAnnotations.search(SearchStrategy.TYPE_HIERARCHY)
.withEnclosingClasses(searchEnclosingClass)
.from(clazz)
.get(annotationType)
.synthesize(MergedAnnotation::isPresent).orElse(null);
.get(annotationType);
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2024 the original author or authors.
* Copyright 2002-2025 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -31,6 +31,7 @@
import org.springframework.core.SpringProperties;
import org.springframework.core.annotation.AliasFor;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.annotation.MergedAnnotation;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
Expand All @@ -48,12 +49,40 @@
* Tests for {@link TestContextAnnotationUtils}.
*
* @author Sam Brannen
* @author Yanming Zhou
* @since 5.3, though originally since 4.0 for the deprecated
* {@link org.springframework.test.util.MetaAnnotationUtils} support
* @see OverriddenMetaAnnotationAttributesTestContextAnnotationUtilsTests
*/
class TestContextAnnotationUtilsTests {

@Nested
@DisplayName("findMergedAnnotation() tests")
class FindMergedAnnotationTests {

@Test
void findMergedAnnotation() {
Class<?> startClass = MetaConfigWithDefaultAttributesTestCase.class;
Class<ContextConfiguration> annotationType = ContextConfiguration.class;

ContextConfiguration annotation = TestContextAnnotationUtils.findMergedAnnotation(startClass, annotationType);

assertThat(annotation).isNotNull();
assertThat(annotation.classes()).containsExactlyInAnyOrder(MetaConfig.DevConfig.class, MetaConfig.ProductionConfig.class);
}

@Test
void getMergedAnnotation() {
Class<?> startClass = MetaConfigWithDefaultAttributesTestCase.class;
Class<ContextConfiguration> annotationType = ContextConfiguration.class;

MergedAnnotation<ContextConfiguration> annotation = TestContextAnnotationUtils.getMergedAnnotation(startClass, annotationType);

assertThat(annotation.isPresent()).isTrue();
assertThat(annotation.getClassArray("classes")).containsExactlyInAnyOrder(MetaConfig.DevConfig.class, MetaConfig.ProductionConfig.class);
}
}

@Nested
@DisplayName("searchEnclosingClass() tests")
class SearchEnclosingClassTests {
Expand Down