1+ package play ;
2+
3+ import org .junit .jupiter .api .Nested ;
4+ import org .junit .jupiter .api .Test ;
5+
6+ import java .lang .annotation .Annotation ;
7+ import java .lang .reflect .InvocationHandler ;
8+ import java .lang .reflect .Proxy ;
9+ import java .util .Arrays ;
10+ import java .util .List ;
11+ import java .util .function .Consumer ;
12+ import java .util .stream .Stream ;
13+
14+ import static org .assertj .core .api .Assertions .assertThat ;
15+
16+ class InvokerTest {
17+
18+ @ Nested
19+ class InvocationContextTest {
20+
21+ @ Test void constructorStringShouldCreateInvocationContextWithEmptyAnnotationsCollection () {
22+ String invocationType = "constructorString" ;
23+ var context = new Invoker .InvocationContext (invocationType );
24+ assertThat (context .getInvocationType ()).isSameAs (invocationType );
25+ assertThat (context .getAnnotations ()).isEmpty ();
26+ }
27+
28+ @ Test void constructorStringAndListShouldCreateInvocationContextWithSameAnnotationsCollection () {
29+ String invocationType = "constructorStringAndList" ;
30+ var annotations = List .of (stubAnnotationsFor (A .class , B .class , C .class , D .class ));
31+ var context = new Invoker .InvocationContext (invocationType , annotations );
32+ assertThat (context .getInvocationType ()).isSameAs (invocationType );
33+ assertThat (context .getAnnotations ()).isSameAs (annotations );
34+ }
35+
36+ @ Test void constructorStringAndOneDimensionArrayShouldCreateInvocationContextWithAnnotationsCollectionFromArray () {
37+ String invocationType = "constructorStringAndOneDimensionArray" ;
38+ var annotations = stubAnnotationsFor (A .class , B .class , C .class , D .class );
39+ var context = new Invoker .InvocationContext (invocationType , annotations );
40+
41+ assertThat (context .getInvocationType ()).isSameAs (invocationType );
42+ assertThat (context .getAnnotations ()).satisfiesExactly (
43+ Arrays .stream (annotations )
44+ .<Consumer <? super Annotation >>map (annotation -> actual -> assertThat (actual ).isSameAs (annotation ))
45+ .toArray (Consumer []::new )
46+ );
47+ }
48+
49+ @ Test void constructorStringAndTwoDimensionsArrayShouldCreateInvocationContextWithAnnotationsCollectionFromArray () {
50+ String invocationType = "constructorStringAndTwoDimensionsArray" ;
51+ var abAnnotations = stubAnnotationsFor (A .class , B .class );
52+ var cdAnnotations = stubAnnotationsFor (C .class , D .class );
53+ var context = new Invoker .InvocationContext (invocationType , abAnnotations , cdAnnotations );
54+
55+ assertThat (context .getInvocationType ()).isSameAs (invocationType );
56+ assertThat (context .getAnnotations ()).satisfiesExactly (
57+ Stream .concat (Arrays .stream (abAnnotations ), Arrays .stream (cdAnnotations ))
58+ .<Consumer <? super Annotation >>map (annotation -> actual -> assertThat (actual ).isSameAs (annotation ))
59+ .toArray (Consumer []::new )
60+ );
61+ }
62+
63+ @ Test void getAnnotationShouldReturnFirstAnnotationFromList () {
64+ var annotations = stubAnnotationsFor (A .class , B .class , C .class , B .class );
65+ var context = new Invoker .InvocationContext ("someInvocationType" , annotations );
66+ assertThat (context .getAnnotation (B .class )).isSameAs (annotations [1 ]);
67+ }
68+
69+ @ Test void getAnnotationShouldReturnNull () {
70+ var context = new Invoker .InvocationContext ("someInvocationType" , stubAnnotationsFor (A .class , B .class , C .class ));
71+ assertThat (context .getAnnotation (D .class )).isNull ();
72+ }
73+
74+ @ Test void isAnnotationPresentShouldReturnTrue () {
75+ var annotations = stubAnnotationsFor (A .class , B .class , C .class , B .class );
76+ var context = new Invoker .InvocationContext ("someInvocationType" , annotations );
77+ assertThat (context .isAnnotationPresent (C .class )).isTrue ();
78+ }
79+
80+ @ Test void isAnnotationPresentShouldReturnFalse () {
81+ var context = new Invoker .InvocationContext ("someInvocationType" , stubAnnotationsFor (A .class , B .class , C .class ));
82+ assertThat (context .isAnnotationPresent (D .class )).isFalse ();
83+ }
84+
85+ @ SafeVarargs
86+ private Annotation [] stubAnnotationsFor (Class <? extends Annotation >... annotations ) {
87+ return Arrays .stream (annotations ).map (this ::stubAnnotationFor ).toArray (Annotation []::new );
88+ }
89+
90+ private <T extends Annotation > T stubAnnotationFor (Class <T > annotation ) {
91+ InvocationHandler handler = (proxy , method , args ) ->
92+ method .getName ().equals ("annotationType" ) ? annotation : method .invoke (proxy , args );
93+
94+ return (T ) Proxy .newProxyInstance (annotation .getClassLoader (), new Class [] { annotation }, handler );
95+ }
96+
97+ private @interface A {}
98+ private @interface B {}
99+ private @interface C {}
100+ private @interface D {}
101+
102+ }
103+
104+
105+ }
0 commit comments