Revise RepeatableContainersTests
This commit is contained in:
@@ -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,193 +33,166 @@ 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,
|
@Test
|
||||||
NonRepeatable.class);
|
void standardRepeatablesWhenNonRepeatableReturnsNull() {
|
||||||
assertThat(values).isNull();
|
Object[] values = findRepeatedAnnotationValues(RepeatableContainers.standardRepeatables(),
|
||||||
|
NonRepeatableTestCase.class, NonRepeatable.class);
|
||||||
|
assertThat(values).isNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void standardRepeatablesWhenSingleReturnsNull() {
|
||||||
|
Object[] values = findRepeatedAnnotationValues(RepeatableContainers.standardRepeatables(),
|
||||||
|
SingleStandardRepeatableTestCase.class, StandardRepeatable.class);
|
||||||
|
assertThat(values).isNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void standardRepeatablesWhenContainerButNotRepeatableReturnsNull() {
|
||||||
|
Object[] values = findRepeatedAnnotationValues(RepeatableContainers.standardRepeatables(),
|
||||||
|
ExplicitRepeatablesTestCase.class, ExplicitContainer.class);
|
||||||
|
assertThat(values).isNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void standardRepeatablesWhenContainerReturnsRepeats() {
|
||||||
|
Object[] values = findRepeatedAnnotationValues(RepeatableContainers.standardRepeatables(),
|
||||||
|
StandardRepeatablesTestCase.class, StandardContainer.class);
|
||||||
|
assertThat(values).containsExactly("a", "b");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Nested
|
||||||
void standardRepeatablesWhenSingleReturnsNull() {
|
class ExplicitRepeatableContainerTests {
|
||||||
Object[] values = findRepeatedAnnotationValues(
|
|
||||||
RepeatableContainers.standardRepeatables(),
|
|
||||||
WithSingleStandardRepeatable.class, StandardRepeatable.class);
|
|
||||||
assertThat(values).isNull();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void standardRepeatablesWhenContainerReturnsRepeats() {
|
void ofExplicitWhenNonRepeatableReturnsNull() {
|
||||||
Object[] values = findRepeatedAnnotationValues(
|
Object[] values = findRepeatedAnnotationValues(
|
||||||
RepeatableContainers.standardRepeatables(), WithStandardRepeatables.class,
|
RepeatableContainers.of(ExplicitRepeatable.class, ExplicitContainer.class),
|
||||||
StandardContainer.class);
|
NonRepeatableTestCase.class, NonRepeatable.class);
|
||||||
assertThat(values).containsExactly("a", "b");
|
assertThat(values).isNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void standardRepeatablesWhenContainerButNotRepeatableReturnsNull() {
|
void ofExplicitWhenStandardRepeatableContainerReturnsNull() {
|
||||||
Object[] values = findRepeatedAnnotationValues(
|
Object[] values = findRepeatedAnnotationValues(
|
||||||
RepeatableContainers.standardRepeatables(), WithExplicitRepeatables.class,
|
RepeatableContainers.of(ExplicitRepeatable.class, ExplicitContainer.class),
|
||||||
ExplicitContainer.class);
|
StandardRepeatablesTestCase.class, StandardContainer.class);
|
||||||
assertThat(values).isNull();
|
assertThat(values).isNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void ofExplicitWhenNonRepeatableReturnsNull() {
|
void ofExplicitWhenContainerReturnsRepeats() {
|
||||||
Object[] values = findRepeatedAnnotationValues(
|
Object[] values = findRepeatedAnnotationValues(
|
||||||
RepeatableContainers.of(ExplicitRepeatable.class,
|
RepeatableContainers.of(ExplicitRepeatable.class, ExplicitContainer.class),
|
||||||
ExplicitContainer.class),
|
ExplicitRepeatablesTestCase.class, ExplicitContainer.class);
|
||||||
WithNonRepeatable.class, NonRepeatable.class);
|
assertThat(values).containsExactly("a", "b");
|
||||||
assertThat(values).isNull();
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void ofExplicitWhenStandardRepeatableContainerReturnsNull() {
|
void ofExplicitWhenContainerIsNullDeducesContainer() {
|
||||||
Object[] values = findRepeatedAnnotationValues(
|
Object[] values = findRepeatedAnnotationValues(RepeatableContainers.of(StandardRepeatable.class, null),
|
||||||
RepeatableContainers.of(ExplicitRepeatable.class,
|
StandardRepeatablesTestCase.class, StandardContainer.class);
|
||||||
ExplicitContainer.class),
|
assertThat(values).containsExactly("a", "b");
|
||||||
WithStandardRepeatables.class, StandardContainer.class);
|
}
|
||||||
assertThat(values).isNull();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void ofExplicitWhenContainerReturnsRepeats() {
|
void ofExplicitWhenHasNoValueThrowsException() {
|
||||||
Object[] values = findRepeatedAnnotationValues(
|
assertThatExceptionOfType(AnnotationConfigurationException.class)
|
||||||
RepeatableContainers.of(ExplicitRepeatable.class,
|
.isThrownBy(() -> RepeatableContainers.of(ExplicitRepeatable.class, InvalidNoValue.class))
|
||||||
ExplicitContainer.class),
|
.withMessageContaining("Invalid declaration of container type [%s] for repeatable annotation [%s]",
|
||||||
WithExplicitRepeatables.class, ExplicitContainer.class);
|
InvalidNoValue.class.getName(), ExplicitRepeatable.class.getName());
|
||||||
assertThat(values).containsExactly("a", "b");
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void ofExplicitWhenHasNoValueThrowsException() {
|
void ofExplicitWhenValueIsNotArrayThrowsException() {
|
||||||
assertThatExceptionOfType(AnnotationConfigurationException.class).isThrownBy(() ->
|
assertThatExceptionOfType(AnnotationConfigurationException.class)
|
||||||
RepeatableContainers.of(ExplicitRepeatable.class, InvalidNoValue.class))
|
.isThrownBy(() -> RepeatableContainers.of(ExplicitRepeatable.class, InvalidNotArray.class))
|
||||||
.withMessageContaining("Invalid declaration of container type ["
|
.withMessage("Container type [%s] must declare a 'value' attribute for an array of type [%s]",
|
||||||
+ InvalidNoValue.class.getName()
|
InvalidNotArray.class.getName(), ExplicitRepeatable.class.getName());
|
||||||
+ "] for repeatable annotation ["
|
}
|
||||||
+ ExplicitRepeatable.class.getName() + "]");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void ofExplicitWhenValueIsNotArrayThrowsException() {
|
void ofExplicitWhenValueIsArrayOfWrongTypeThrowsException() {
|
||||||
assertThatExceptionOfType(AnnotationConfigurationException.class).isThrownBy(() ->
|
assertThatExceptionOfType(AnnotationConfigurationException.class)
|
||||||
RepeatableContainers.of(ExplicitRepeatable.class, InvalidNotArray.class))
|
.isThrownBy(() -> RepeatableContainers.of(ExplicitRepeatable.class, InvalidWrongArrayType.class))
|
||||||
.withMessage("Container type ["
|
.withMessage("Container type [%s] must declare a 'value' attribute for an array of type [%s]",
|
||||||
+ InvalidNotArray.class.getName()
|
InvalidWrongArrayType.class.getName(), ExplicitRepeatable.class.getName());
|
||||||
+ "] must declare a 'value' attribute for an array of type ["
|
}
|
||||||
+ ExplicitRepeatable.class.getName() + "]");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void ofExplicitWhenValueIsArrayOfWrongTypeThrowsException() {
|
void ofExplicitWhenAnnotationIsNullThrowsException() {
|
||||||
assertThatExceptionOfType(AnnotationConfigurationException.class).isThrownBy(() ->
|
assertThatIllegalArgumentException()
|
||||||
RepeatableContainers.of(ExplicitRepeatable.class, InvalidWrongArrayType.class))
|
.isThrownBy(() -> RepeatableContainers.of(null, null))
|
||||||
.withMessage("Container type ["
|
.withMessage("Repeatable must not be null");
|
||||||
+ InvalidWrongArrayType.class.getName()
|
}
|
||||||
+ "] must declare a 'value' attribute for an array of type ["
|
|
||||||
+ ExplicitRepeatable.class.getName() + "]");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void ofExplicitWhenAnnotationIsNullThrowsException() {
|
void ofExplicitWhenContainerIsNullAndNotRepeatableThrowsException() {
|
||||||
assertThatIllegalArgumentException().isThrownBy(() ->
|
assertThatIllegalArgumentException()
|
||||||
RepeatableContainers.of(null, null))
|
.isThrownBy(() -> RepeatableContainers.of(ExplicitRepeatable.class, null))
|
||||||
.withMessage("Repeatable must not be null");
|
.withMessage("Annotation type must be a repeatable annotation: failed to resolve container type for %s",
|
||||||
}
|
ExplicitRepeatable.class.getName());
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
void ofExplicitWhenContainerIsNullDeducesContainer() {
|
|
||||||
Object[] values = findRepeatedAnnotationValues(
|
|
||||||
RepeatableContainers.of(StandardRepeatable.class, null),
|
|
||||||
WithStandardRepeatables.class, StandardContainer.class);
|
|
||||||
assertThat(values).containsExactly("a", "b");
|
|
||||||
}
|
|
||||||
|
|
||||||
@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)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@interface NonRepeatable {
|
@interface NonRepeatable {
|
||||||
|
|
||||||
String value() default "";
|
String value() default "";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
|
||||||
@Repeatable(StandardContainer.class)
|
|
||||||
@interface StandardRepeatable {
|
|
||||||
|
|
||||||
String value() default "";
|
|
||||||
}
|
|
||||||
|
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@interface StandardContainer {
|
@interface StandardContainer {
|
||||||
|
|
||||||
@@ -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 {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user