Revise RepeatableContainersTests
This commit is contained in:
		
							parent
							
								
									c7bdfbea4f
								
							
						
					
					
						commit
						0b08246760
					
				|  | @ -20,7 +20,9 @@ import java.lang.annotation.Annotation; | |||
| import java.lang.annotation.Repeatable; | ||||
| import java.lang.annotation.Retention; | ||||
| import java.lang.annotation.RetentionPolicy; | ||||
| import java.util.Arrays; | ||||
| 
 | ||||
| import org.junit.jupiter.api.Nested; | ||||
| import org.junit.jupiter.api.Test; | ||||
| 
 | ||||
| import static org.assertj.core.api.Assertions.assertThat; | ||||
|  | @ -31,193 +33,166 @@ import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException | |||
|  * Tests for {@link RepeatableContainers}. | ||||
|  * | ||||
|  * @author Phillip Webb | ||||
|  * @author Sam Brannen | ||||
|  */ | ||||
| class RepeatableContainersTests { | ||||
| 
 | ||||
| 	@Nested | ||||
| 	class StandardRepeatableContainersTests { | ||||
| 
 | ||||
| 		@Test | ||||
| 		void standardRepeatablesWhenNonRepeatableReturnsNull() { | ||||
| 		Object[] values = findRepeatedAnnotationValues( | ||||
| 				RepeatableContainers.standardRepeatables(), WithNonRepeatable.class, | ||||
| 				NonRepeatable.class); | ||||
| 			Object[] values = findRepeatedAnnotationValues(RepeatableContainers.standardRepeatables(), | ||||
| 				NonRepeatableTestCase.class, NonRepeatable.class); | ||||
| 			assertThat(values).isNull(); | ||||
| 		} | ||||
| 
 | ||||
| 		@Test | ||||
| 		void standardRepeatablesWhenSingleReturnsNull() { | ||||
| 		Object[] values = findRepeatedAnnotationValues( | ||||
| 				RepeatableContainers.standardRepeatables(), | ||||
| 				WithSingleStandardRepeatable.class, StandardRepeatable.class); | ||||
| 			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(), WithStandardRepeatables.class, | ||||
| 				StandardContainer.class); | ||||
| 			Object[] values = findRepeatedAnnotationValues(RepeatableContainers.standardRepeatables(), | ||||
| 				StandardRepeatablesTestCase.class, StandardContainer.class); | ||||
| 			assertThat(values).containsExactly("a", "b"); | ||||
| 		} | ||||
| 
 | ||||
| 	@Test | ||||
| 	void standardRepeatablesWhenContainerButNotRepeatableReturnsNull() { | ||||
| 		Object[] values = findRepeatedAnnotationValues( | ||||
| 				RepeatableContainers.standardRepeatables(), WithExplicitRepeatables.class, | ||||
| 				ExplicitContainer.class); | ||||
| 		assertThat(values).isNull(); | ||||
| 	} | ||||
| 
 | ||||
| 	@Nested | ||||
| 	class ExplicitRepeatableContainerTests { | ||||
| 
 | ||||
| 		@Test | ||||
| 		void ofExplicitWhenNonRepeatableReturnsNull() { | ||||
| 			Object[] values = findRepeatedAnnotationValues( | ||||
| 				RepeatableContainers.of(ExplicitRepeatable.class, | ||||
| 						ExplicitContainer.class), | ||||
| 				WithNonRepeatable.class, NonRepeatable.class); | ||||
| 				RepeatableContainers.of(ExplicitRepeatable.class, ExplicitContainer.class), | ||||
| 				NonRepeatableTestCase.class, NonRepeatable.class); | ||||
| 			assertThat(values).isNull(); | ||||
| 		} | ||||
| 
 | ||||
| 		@Test | ||||
| 		void ofExplicitWhenStandardRepeatableContainerReturnsNull() { | ||||
| 			Object[] values = findRepeatedAnnotationValues( | ||||
| 				RepeatableContainers.of(ExplicitRepeatable.class, | ||||
| 						ExplicitContainer.class), | ||||
| 				WithStandardRepeatables.class, StandardContainer.class); | ||||
| 				RepeatableContainers.of(ExplicitRepeatable.class, ExplicitContainer.class), | ||||
| 				StandardRepeatablesTestCase.class, StandardContainer.class); | ||||
| 			assertThat(values).isNull(); | ||||
| 		} | ||||
| 
 | ||||
| 		@Test | ||||
| 		void ofExplicitWhenContainerReturnsRepeats() { | ||||
| 			Object[] values = findRepeatedAnnotationValues( | ||||
| 				RepeatableContainers.of(ExplicitRepeatable.class, | ||||
| 						ExplicitContainer.class), | ||||
| 				WithExplicitRepeatables.class, ExplicitContainer.class); | ||||
| 				RepeatableContainers.of(ExplicitRepeatable.class, ExplicitContainer.class), | ||||
| 				ExplicitRepeatablesTestCase.class, ExplicitContainer.class); | ||||
| 			assertThat(values).containsExactly("a", "b"); | ||||
| 		} | ||||
| 
 | ||||
| 		@Test | ||||
| 		void ofExplicitWhenContainerIsNullDeducesContainer() { | ||||
| 			Object[] values = findRepeatedAnnotationValues(RepeatableContainers.of(StandardRepeatable.class, null), | ||||
| 				StandardRepeatablesTestCase.class, StandardContainer.class); | ||||
| 			assertThat(values).containsExactly("a", "b"); | ||||
| 		} | ||||
| 
 | ||||
| 		@Test | ||||
| 		void ofExplicitWhenHasNoValueThrowsException() { | ||||
| 		assertThatExceptionOfType(AnnotationConfigurationException.class).isThrownBy(() -> | ||||
| 				RepeatableContainers.of(ExplicitRepeatable.class, InvalidNoValue.class)) | ||||
| 			.withMessageContaining("Invalid declaration of container type [" | ||||
| 									+ InvalidNoValue.class.getName() | ||||
| 									+ "] for repeatable annotation [" | ||||
| 									+ ExplicitRepeatable.class.getName() + "]"); | ||||
| 			assertThatExceptionOfType(AnnotationConfigurationException.class) | ||||
| 				.isThrownBy(() -> RepeatableContainers.of(ExplicitRepeatable.class, InvalidNoValue.class)) | ||||
| 				.withMessageContaining("Invalid declaration of container type [%s] for repeatable annotation [%s]", | ||||
| 					InvalidNoValue.class.getName(), ExplicitRepeatable.class.getName()); | ||||
| 		} | ||||
| 
 | ||||
| 		@Test | ||||
| 		void ofExplicitWhenValueIsNotArrayThrowsException() { | ||||
| 		assertThatExceptionOfType(AnnotationConfigurationException.class).isThrownBy(() -> | ||||
| 				RepeatableContainers.of(ExplicitRepeatable.class, InvalidNotArray.class)) | ||||
| 			.withMessage("Container type [" | ||||
| 								+ InvalidNotArray.class.getName() | ||||
| 								+ "] must declare a 'value' attribute for an array of type [" | ||||
| 								+ ExplicitRepeatable.class.getName() + "]"); | ||||
| 			assertThatExceptionOfType(AnnotationConfigurationException.class) | ||||
| 				.isThrownBy(() -> RepeatableContainers.of(ExplicitRepeatable.class, InvalidNotArray.class)) | ||||
| 				.withMessage("Container type [%s] must declare a 'value' attribute for an array of type [%s]", | ||||
| 					InvalidNotArray.class.getName(), ExplicitRepeatable.class.getName()); | ||||
| 		} | ||||
| 
 | ||||
| 		@Test | ||||
| 		void ofExplicitWhenValueIsArrayOfWrongTypeThrowsException() { | ||||
| 		assertThatExceptionOfType(AnnotationConfigurationException.class).isThrownBy(() -> | ||||
| 				RepeatableContainers.of(ExplicitRepeatable.class, InvalidWrongArrayType.class)) | ||||
| 			.withMessage("Container type [" | ||||
| 								+ InvalidWrongArrayType.class.getName() | ||||
| 								+ "] must declare a 'value' attribute for an array of type [" | ||||
| 								+ ExplicitRepeatable.class.getName() + "]"); | ||||
| 			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)) | ||||
| 			assertThatIllegalArgumentException() | ||||
| 				.isThrownBy(() -> RepeatableContainers.of(null, null)) | ||||
| 				.withMessage("Repeatable must not be null"); | ||||
| 		} | ||||
| 
 | ||||
| 		@Test | ||||
| 	void ofExplicitWhenContainerIsNullDeducesContainer() { | ||||
| 		Object[] values = findRepeatedAnnotationValues( | ||||
| 				RepeatableContainers.of(StandardRepeatable.class, null), | ||||
| 				WithStandardRepeatables.class, StandardContainer.class); | ||||
| 		assertThat(values).containsExactly("a", "b"); | ||||
| 		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 | ||||
| 	void standardAndExplicitReturnsRepeats() { | ||||
| 		RepeatableContainers repeatableContainers = RepeatableContainers.standardRepeatables().and( | ||||
| 				ExplicitContainer.class, ExplicitRepeatable.class); | ||||
| 		assertThat(findRepeatedAnnotationValues(repeatableContainers, | ||||
| 				WithStandardRepeatables.class, StandardContainer.class)).containsExactly( | ||||
| 						"a", "b"); | ||||
| 		assertThat(findRepeatedAnnotationValues(repeatableContainers, | ||||
| 				WithExplicitRepeatables.class, ExplicitContainer.class)).containsExactly( | ||||
| 						"a", "b"); | ||||
| 		RepeatableContainers repeatableContainers = RepeatableContainers.standardRepeatables() | ||||
| 			.and(ExplicitContainer.class, ExplicitRepeatable.class); | ||||
| 		assertThat(findRepeatedAnnotationValues(repeatableContainers, StandardRepeatablesTestCase.class, StandardContainer.class)) | ||||
| 			.containsExactly("a", "b"); | ||||
| 		assertThat(findRepeatedAnnotationValues(repeatableContainers, ExplicitRepeatablesTestCase.class, ExplicitContainer.class)) | ||||
| 			.containsExactly("a", "b"); | ||||
| 	} | ||||
| 
 | ||||
| 	@Test | ||||
| 	void noneAlwaysReturnsNull() { | ||||
| 		Object[] values = findRepeatedAnnotationValues( | ||||
| 				RepeatableContainers.none(), WithStandardRepeatables.class, | ||||
| 		Object[] values = findRepeatedAnnotationValues(RepeatableContainers.none(), StandardRepeatablesTestCase.class, | ||||
| 			StandardContainer.class); | ||||
| 		assertThat(values).isNull(); | ||||
| 	} | ||||
| 
 | ||||
| 	@Test | ||||
| 	void equalsAndHashcode() { | ||||
| 		RepeatableContainers c1 = RepeatableContainers.of(ExplicitRepeatable.class, | ||||
| 				ExplicitContainer.class); | ||||
| 		RepeatableContainers c2 = RepeatableContainers.of(ExplicitRepeatable.class, | ||||
| 				ExplicitContainer.class); | ||||
| 		RepeatableContainers c1 = RepeatableContainers.of(ExplicitRepeatable.class, ExplicitContainer.class); | ||||
| 		RepeatableContainers c2 = RepeatableContainers.of(ExplicitRepeatable.class, ExplicitContainer.class); | ||||
| 		RepeatableContainers c3 = RepeatableContainers.standardRepeatables(); | ||||
| 		RepeatableContainers c4 = RepeatableContainers.standardRepeatables().and( | ||||
| 				ExplicitContainer.class, ExplicitRepeatable.class); | ||||
| 		assertThat(c1.hashCode()).isEqualTo(c2.hashCode()); | ||||
| 		RepeatableContainers c4 = RepeatableContainers.standardRepeatables().and(ExplicitContainer.class, ExplicitRepeatable.class); | ||||
| 		assertThat(c1).hasSameHashCodeAs(c2); | ||||
| 		assertThat(c1).isEqualTo(c1).isEqualTo(c2); | ||||
| 		assertThat(c1).isNotEqualTo(c3).isNotEqualTo(c4); | ||||
| 	} | ||||
| 
 | ||||
| 	private Object[] findRepeatedAnnotationValues(RepeatableContainers containers, | ||||
| 
 | ||||
| 	private static Object[] findRepeatedAnnotationValues(RepeatableContainers containers, | ||||
| 			Class<?> element, Class<? extends Annotation> annotationType) { | ||||
| 		Annotation[] annotations = containers.findRepeatedAnnotations( | ||||
| 				element.getAnnotation(annotationType)); | ||||
| 		Annotation[] annotations = containers.findRepeatedAnnotations(element.getAnnotation(annotationType)); | ||||
| 		return extractValues(annotations); | ||||
| 	} | ||||
| 
 | ||||
| 	private Object[] extractValues(Annotation[] annotations) { | ||||
| 		try { | ||||
| 	private static Object[] extractValues(Annotation[] annotations) { | ||||
| 		if (annotations == 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) | ||||
| 	@Repeatable(StandardContainer.class) | ||||
| 	@interface StandardRepeatable { | ||||
| 
 | ||||
| 		String value() default ""; | ||||
| 	} | ||||
| 
 | ||||
| 	@Retention(RetentionPolicy.RUNTIME) | ||||
| 	@interface StandardContainer { | ||||
| 
 | ||||
|  | @ -225,7 +200,8 @@ class RepeatableContainersTests { | |||
| 	} | ||||
| 
 | ||||
| 	@Retention(RetentionPolicy.RUNTIME) | ||||
| 	@interface ExplicitRepeatable { | ||||
| 	@Repeatable(StandardContainer.class) | ||||
| 	@interface StandardRepeatable { | ||||
| 
 | ||||
| 		String value() default ""; | ||||
| 	} | ||||
|  | @ -236,6 +212,12 @@ class RepeatableContainersTests { | |||
| 		ExplicitRepeatable[] value(); | ||||
| 	} | ||||
| 
 | ||||
| 	@Retention(RetentionPolicy.RUNTIME) | ||||
| 	@interface ExplicitRepeatable { | ||||
| 
 | ||||
| 		String value() default ""; | ||||
| 	} | ||||
| 
 | ||||
| 	@Retention(RetentionPolicy.RUNTIME) | ||||
| 	@interface InvalidNoValue { | ||||
| 	} | ||||
|  | @ -253,20 +235,20 @@ class RepeatableContainersTests { | |||
| 	} | ||||
| 
 | ||||
| 	@NonRepeatable("a") | ||||
| 	static class WithNonRepeatable { | ||||
| 	static class NonRepeatableTestCase { | ||||
| 	} | ||||
| 
 | ||||
| 	@StandardRepeatable("a") | ||||
| 	static class WithSingleStandardRepeatable { | ||||
| 	static class SingleStandardRepeatableTestCase { | ||||
| 	} | ||||
| 
 | ||||
| 	@StandardRepeatable("a") | ||||
| 	@StandardRepeatable("b") | ||||
| 	static class WithStandardRepeatables { | ||||
| 	static class StandardRepeatablesTestCase { | ||||
| 	} | ||||
| 
 | ||||
| 	@ExplicitContainer({ @ExplicitRepeatable("a"), @ExplicitRepeatable("b") }) | ||||
| 	static class WithExplicitRepeatables { | ||||
| 	static class ExplicitRepeatablesTestCase { | ||||
| 	} | ||||
| 
 | ||||
| } | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue