Browse Source

Revise RepeatableContainersTests

pull/29692/head
Sam Brannen 3 years ago
parent
commit
0b08246760
  1. 272
      spring-core/src/test/java/org/springframework/core/annotation/RepeatableContainersTests.java

272
spring-core/src/test/java/org/springframework/core/annotation/RepeatableContainersTests.java

@ -20,7 +20,9 @@ import java.lang.annotation.Annotation;
import java.lang.annotation.Repeatable; import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.util.Arrays;
import org.junit.jupiter.api.Nested;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThat;
@ -31,189 +33,162 @@ import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException
* Tests for {@link RepeatableContainers}. * Tests for {@link RepeatableContainers}.
* *
* @author Phillip Webb * @author Phillip Webb
* @author Sam Brannen
*/ */
class RepeatableContainersTests { class RepeatableContainersTests {
@Test @Nested
void standardRepeatablesWhenNonRepeatableReturnsNull() { class StandardRepeatableContainersTests {
Object[] values = findRepeatedAnnotationValues(
RepeatableContainers.standardRepeatables(), WithNonRepeatable.class,
NonRepeatable.class);
assertThat(values).isNull();
}
@Test @Test
void standardRepeatablesWhenSingleReturnsNull() { void standardRepeatablesWhenNonRepeatableReturnsNull() {
Object[] values = findRepeatedAnnotationValues( Object[] values = findRepeatedAnnotationValues(RepeatableContainers.standardRepeatables(),
RepeatableContainers.standardRepeatables(), NonRepeatableTestCase.class, NonRepeatable.class);
WithSingleStandardRepeatable.class, StandardRepeatable.class); assertThat(values).isNull();
assertThat(values).isNull(); }
}
@Test @Test
void standardRepeatablesWhenContainerReturnsRepeats() { void standardRepeatablesWhenSingleReturnsNull() {
Object[] values = findRepeatedAnnotationValues( Object[] values = findRepeatedAnnotationValues(RepeatableContainers.standardRepeatables(),
RepeatableContainers.standardRepeatables(), WithStandardRepeatables.class, SingleStandardRepeatableTestCase.class, StandardRepeatable.class);
StandardContainer.class); assertThat(values).isNull();
assertThat(values).containsExactly("a", "b"); }
}
@Test @Test
void standardRepeatablesWhenContainerButNotRepeatableReturnsNull() { void standardRepeatablesWhenContainerButNotRepeatableReturnsNull() {
Object[] values = findRepeatedAnnotationValues( Object[] values = findRepeatedAnnotationValues(RepeatableContainers.standardRepeatables(),
RepeatableContainers.standardRepeatables(), WithExplicitRepeatables.class, ExplicitRepeatablesTestCase.class, ExplicitContainer.class);
ExplicitContainer.class); assertThat(values).isNull();
assertThat(values).isNull(); }
}
@Test @Test
void ofExplicitWhenNonRepeatableReturnsNull() { void standardRepeatablesWhenContainerReturnsRepeats() {
Object[] values = findRepeatedAnnotationValues( Object[] values = findRepeatedAnnotationValues(RepeatableContainers.standardRepeatables(),
RepeatableContainers.of(ExplicitRepeatable.class, StandardRepeatablesTestCase.class, StandardContainer.class);
ExplicitContainer.class), assertThat(values).containsExactly("a", "b");
WithNonRepeatable.class, NonRepeatable.class); }
assertThat(values).isNull();
} }
@Test @Nested
void ofExplicitWhenStandardRepeatableContainerReturnsNull() { class ExplicitRepeatableContainerTests {
Object[] values = findRepeatedAnnotationValues(
RepeatableContainers.of(ExplicitRepeatable.class,
ExplicitContainer.class),
WithStandardRepeatables.class, StandardContainer.class);
assertThat(values).isNull();
}
@Test @Test
void ofExplicitWhenContainerReturnsRepeats() { void ofExplicitWhenNonRepeatableReturnsNull() {
Object[] values = findRepeatedAnnotationValues( Object[] values = findRepeatedAnnotationValues(
RepeatableContainers.of(ExplicitRepeatable.class, RepeatableContainers.of(ExplicitRepeatable.class, ExplicitContainer.class),
ExplicitContainer.class), NonRepeatableTestCase.class, NonRepeatable.class);
WithExplicitRepeatables.class, ExplicitContainer.class); assertThat(values).isNull();
assertThat(values).containsExactly("a", "b"); }
}
@Test @Test
void ofExplicitWhenHasNoValueThrowsException() { void ofExplicitWhenStandardRepeatableContainerReturnsNull() {
assertThatExceptionOfType(AnnotationConfigurationException.class).isThrownBy(() -> Object[] values = findRepeatedAnnotationValues(
RepeatableContainers.of(ExplicitRepeatable.class, InvalidNoValue.class)) RepeatableContainers.of(ExplicitRepeatable.class, ExplicitContainer.class),
.withMessageContaining("Invalid declaration of container type [" StandardRepeatablesTestCase.class, StandardContainer.class);
+ InvalidNoValue.class.getName() assertThat(values).isNull();
+ "] for repeatable annotation [" }
+ ExplicitRepeatable.class.getName() + "]");
}
@Test @Test
void ofExplicitWhenValueIsNotArrayThrowsException() { void ofExplicitWhenContainerReturnsRepeats() {
assertThatExceptionOfType(AnnotationConfigurationException.class).isThrownBy(() -> Object[] values = findRepeatedAnnotationValues(
RepeatableContainers.of(ExplicitRepeatable.class, InvalidNotArray.class)) RepeatableContainers.of(ExplicitRepeatable.class, ExplicitContainer.class),
.withMessage("Container type [" ExplicitRepeatablesTestCase.class, ExplicitContainer.class);
+ InvalidNotArray.class.getName() assertThat(values).containsExactly("a", "b");
+ "] must declare a 'value' attribute for an array of type [" }
+ ExplicitRepeatable.class.getName() + "]");
}
@Test @Test
void ofExplicitWhenValueIsArrayOfWrongTypeThrowsException() { void ofExplicitWhenContainerIsNullDeducesContainer() {
assertThatExceptionOfType(AnnotationConfigurationException.class).isThrownBy(() -> Object[] values = findRepeatedAnnotationValues(RepeatableContainers.of(StandardRepeatable.class, null),
RepeatableContainers.of(ExplicitRepeatable.class, InvalidWrongArrayType.class)) StandardRepeatablesTestCase.class, StandardContainer.class);
.withMessage("Container type [" assertThat(values).containsExactly("a", "b");
+ InvalidWrongArrayType.class.getName() }
+ "] must declare a 'value' attribute for an array of type ["
+ ExplicitRepeatable.class.getName() + "]");
}
@Test @Test
void ofExplicitWhenAnnotationIsNullThrowsException() { void ofExplicitWhenHasNoValueThrowsException() {
assertThatIllegalArgumentException().isThrownBy(() -> assertThatExceptionOfType(AnnotationConfigurationException.class)
RepeatableContainers.of(null, null)) .isThrownBy(() -> RepeatableContainers.of(ExplicitRepeatable.class, InvalidNoValue.class))
.withMessage("Repeatable must not be null"); .withMessageContaining("Invalid declaration of container type [%s] for repeatable annotation [%s]",
} InvalidNoValue.class.getName(), ExplicitRepeatable.class.getName());
}
@Test @Test
void ofExplicitWhenContainerIsNullDeducesContainer() { void ofExplicitWhenValueIsNotArrayThrowsException() {
Object[] values = findRepeatedAnnotationValues( assertThatExceptionOfType(AnnotationConfigurationException.class)
RepeatableContainers.of(StandardRepeatable.class, null), .isThrownBy(() -> RepeatableContainers.of(ExplicitRepeatable.class, InvalidNotArray.class))
WithStandardRepeatables.class, StandardContainer.class); .withMessage("Container type [%s] must declare a 'value' attribute for an array of type [%s]",
assertThat(values).containsExactly("a", "b"); InvalidNotArray.class.getName(), ExplicitRepeatable.class.getName());
} }
@Test
void ofExplicitWhenValueIsArrayOfWrongTypeThrowsException() {
assertThatExceptionOfType(AnnotationConfigurationException.class)
.isThrownBy(() -> RepeatableContainers.of(ExplicitRepeatable.class, InvalidWrongArrayType.class))
.withMessage("Container type [%s] must declare a 'value' attribute for an array of type [%s]",
InvalidWrongArrayType.class.getName(), ExplicitRepeatable.class.getName());
}
@Test
void ofExplicitWhenAnnotationIsNullThrowsException() {
assertThatIllegalArgumentException()
.isThrownBy(() -> RepeatableContainers.of(null, null))
.withMessage("Repeatable must not be null");
}
@Test
void ofExplicitWhenContainerIsNullAndNotRepeatableThrowsException() {
assertThatIllegalArgumentException()
.isThrownBy(() -> RepeatableContainers.of(ExplicitRepeatable.class, null))
.withMessage("Annotation type must be a repeatable annotation: failed to resolve container type for %s",
ExplicitRepeatable.class.getName());
}
@Test
void ofExplicitWhenContainerIsNullAndNotRepeatableThrowsException() {
assertThatIllegalArgumentException().isThrownBy(() ->
RepeatableContainers.of(ExplicitRepeatable.class, null))
.withMessage("Annotation type must be a repeatable annotation: " +
"failed to resolve container type for " +
ExplicitRepeatable.class.getName());
} }
@Test @Test
void standardAndExplicitReturnsRepeats() { void standardAndExplicitReturnsRepeats() {
RepeatableContainers repeatableContainers = RepeatableContainers.standardRepeatables().and( RepeatableContainers repeatableContainers = RepeatableContainers.standardRepeatables()
ExplicitContainer.class, ExplicitRepeatable.class); .and(ExplicitContainer.class, ExplicitRepeatable.class);
assertThat(findRepeatedAnnotationValues(repeatableContainers, assertThat(findRepeatedAnnotationValues(repeatableContainers, StandardRepeatablesTestCase.class, StandardContainer.class))
WithStandardRepeatables.class, StandardContainer.class)).containsExactly( .containsExactly("a", "b");
"a", "b"); assertThat(findRepeatedAnnotationValues(repeatableContainers, ExplicitRepeatablesTestCase.class, ExplicitContainer.class))
assertThat(findRepeatedAnnotationValues(repeatableContainers, .containsExactly("a", "b");
WithExplicitRepeatables.class, ExplicitContainer.class)).containsExactly(
"a", "b");
} }
@Test @Test
void noneAlwaysReturnsNull() { void noneAlwaysReturnsNull() {
Object[] values = findRepeatedAnnotationValues( Object[] values = findRepeatedAnnotationValues(RepeatableContainers.none(), StandardRepeatablesTestCase.class,
RepeatableContainers.none(), WithStandardRepeatables.class, StandardContainer.class);
StandardContainer.class);
assertThat(values).isNull(); assertThat(values).isNull();
} }
@Test @Test
void equalsAndHashcode() { void equalsAndHashcode() {
RepeatableContainers c1 = RepeatableContainers.of(ExplicitRepeatable.class, RepeatableContainers c1 = RepeatableContainers.of(ExplicitRepeatable.class, ExplicitContainer.class);
ExplicitContainer.class); RepeatableContainers c2 = RepeatableContainers.of(ExplicitRepeatable.class, ExplicitContainer.class);
RepeatableContainers c2 = RepeatableContainers.of(ExplicitRepeatable.class,
ExplicitContainer.class);
RepeatableContainers c3 = RepeatableContainers.standardRepeatables(); RepeatableContainers c3 = RepeatableContainers.standardRepeatables();
RepeatableContainers c4 = RepeatableContainers.standardRepeatables().and( RepeatableContainers c4 = RepeatableContainers.standardRepeatables().and(ExplicitContainer.class, ExplicitRepeatable.class);
ExplicitContainer.class, ExplicitRepeatable.class); assertThat(c1).hasSameHashCodeAs(c2);
assertThat(c1.hashCode()).isEqualTo(c2.hashCode());
assertThat(c1).isEqualTo(c1).isEqualTo(c2); assertThat(c1).isEqualTo(c1).isEqualTo(c2);
assertThat(c1).isNotEqualTo(c3).isNotEqualTo(c4); assertThat(c1).isNotEqualTo(c3).isNotEqualTo(c4);
} }
private Object[] findRepeatedAnnotationValues(RepeatableContainers containers,
private static Object[] findRepeatedAnnotationValues(RepeatableContainers containers,
Class<?> element, Class<? extends Annotation> annotationType) { Class<?> element, Class<? extends Annotation> annotationType) {
Annotation[] annotations = containers.findRepeatedAnnotations( Annotation[] annotations = containers.findRepeatedAnnotations(element.getAnnotation(annotationType));
element.getAnnotation(annotationType));
return extractValues(annotations); return extractValues(annotations);
} }
private Object[] extractValues(Annotation[] annotations) { private static Object[] extractValues(Annotation[] annotations) {
try { if (annotations == null) {
if (annotations == null) { return null;
return null;
}
Object[] result = new String[annotations.length];
for (int i = 0; i < annotations.length; i++) {
result[i] = annotations[i].annotationType().getMethod("value").invoke(
annotations[i]);
}
return result;
}
catch (Exception ex) {
throw new RuntimeException(ex);
} }
return Arrays.stream(annotations).map(AnnotationUtils::getValue).toArray(Object[]::new);
} }
@Retention(RetentionPolicy.RUNTIME)
@interface NonRepeatable {
String value() default "";
}
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@Repeatable(StandardContainer.class) @interface NonRepeatable {
@interface StandardRepeatable {
String value() default ""; String value() default "";
} }
@ -225,7 +200,8 @@ class RepeatableContainersTests {
} }
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@interface ExplicitRepeatable { @Repeatable(StandardContainer.class)
@interface StandardRepeatable {
String value() default ""; String value() default "";
} }
@ -236,6 +212,12 @@ class RepeatableContainersTests {
ExplicitRepeatable[] value(); ExplicitRepeatable[] value();
} }
@Retention(RetentionPolicy.RUNTIME)
@interface ExplicitRepeatable {
String value() default "";
}
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@interface InvalidNoValue { @interface InvalidNoValue {
} }
@ -253,20 +235,20 @@ class RepeatableContainersTests {
} }
@NonRepeatable("a") @NonRepeatable("a")
static class WithNonRepeatable { static class NonRepeatableTestCase {
} }
@StandardRepeatable("a") @StandardRepeatable("a")
static class WithSingleStandardRepeatable { static class SingleStandardRepeatableTestCase {
} }
@StandardRepeatable("a") @StandardRepeatable("a")
@StandardRepeatable("b") @StandardRepeatable("b")
static class WithStandardRepeatables { static class StandardRepeatablesTestCase {
} }
@ExplicitContainer({ @ExplicitRepeatable("a"), @ExplicitRepeatable("b") }) @ExplicitContainer({ @ExplicitRepeatable("a"), @ExplicitRepeatable("b") })
static class WithExplicitRepeatables { static class ExplicitRepeatablesTestCase {
} }
} }

Loading…
Cancel
Save