88import org .junit .jupiter .api .Order ;
99import org .junit .jupiter .api .Test ;
1010import org .junit .jupiter .api .TestMethodOrder ;
11+ import org .mockito .Mockito ;
1112
1213import java .lang .reflect .Method ;
13- import java .lang .reflect .Type ;
14+ import java .lang .reflect .ParameterizedType ;
1415import java .math .BigDecimal ;
1516import java .util .Arrays ;
1617import java .util .Comparator ;
2324@ TestMethodOrder (OrderAnnotation .class )
2425class HeterogeneousMaxHolderTest {
2526 private HeterogeneousMaxHolder heterogeneousMaxHolder = new HeterogeneousMaxHolder ();
27+ private HeterogeneousMaxHolder heterogeneousMaxHolderMock = Mockito .spy (HeterogeneousMaxHolder .class );
2628
2729 @ Test
2830 @ Order (1 )
@@ -71,58 +73,53 @@ void putDeclaresOneTypeParam() {
7173 var putMethod = getPutMethod ();
7274
7375 var methodTypeParameters = putMethod .getTypeParameters ();
74-
7576 assertThat (methodTypeParameters ).hasSize (1 );
77+
78+ var typeParam = putMethod .getTypeParameters ()[0 ];
79+ assertThat (typeParam .getName ()).isEqualTo ("T" );
7680 }
7781
7882 @ Test
7983 @ Order (6 )
80- @ DisplayName ("put method type parameter is called 'T' " )
81- void putTypeParamIsCalledT () {
84+ @ DisplayName ("put method accepts type-safe key " )
85+ void putMethodAcceptsTypeSafeKeyParameter () {
8286 var putMethod = getPutMethod ();
8387
84- var typeParam = putMethod .getTypeParameters ()[0 ];
88+ var typeParam = (ParameterizedType ) putMethod .getGenericParameterTypes ()[0 ];
89+ var typeArgument = typeParam .getActualTypeArguments ()[0 ];
8590
86- assertThat (typeParam .getName ()).isEqualTo ("T" );
91+ assertThat (typeParam .getRawType ()).isEqualTo (Class .class );
92+ assertThat (typeArgument .getTypeName ()).isEqualTo ("T" );
8793 }
8894
8995 @ Test
9096 @ Order (7 )
91- @ DisplayName ("type parameter 'T' is declared as Comparable " )
92- void typeParamIsComparable () {
97+ @ DisplayName ("put method accepts comparable value " )
98+ void putMethodAcceptsComparableValueParameter () {
9399 var putMethod = getPutMethod ();
94100
95101 var typeParam = putMethod .getTypeParameters ()[0 ];
96- var bound = typeParam .getBounds ()[0 ];
102+ var boundType = ( ParameterizedType ) typeParam .getBounds ()[0 ];
97103
98- assertThat (bound . getTypeName ()).isEqualTo (Comparable .class . getTypeName () + "<? super T>" );
104+ assertThat (boundType . getRawType ()).isEqualTo (Comparable .class );
99105 }
100106
101107 @ Test
102108 @ Order (8 )
103- @ SneakyThrows
104- @ DisplayName ("put method accepts type (class) and value (object) parameters" )
105- void putHasKeyValueParameters () {
106- HeterogeneousMaxHolder .class .getMethod ("put" , Class .class , Comparable .class );
107- }
109+ @ DisplayName ("put method supports value that has comparable super class" )
110+ void putMethodAcceptsValueParameterWithComparableSuperClass () {
111+ var putMethod = getPutMethod ();
108112
109- @ Test
110- @ Order (9 )
111- @ SneakyThrows
112- @ DisplayName ("put method params specify type arguments" )
113- void putParametersSpecifyTypeArguments () {
114- var putMethod = HeterogeneousMaxHolder .class .getMethod ("put" , Class .class , Comparable .class );
115- var genericParamTypeNames = Arrays .stream (putMethod .getGenericParameterTypes ())
116- .map (Type ::getTypeName )
117- .toList ();
113+ var typeParam = putMethod .getTypeParameters ()[0 ];
114+ var boundType = (ParameterizedType ) typeParam .getBounds ()[0 ];
115+ var typeArgument = boundType .getActualTypeArguments ()[0 ].getTypeName ();
118116
119- assertThat (genericParamTypeNames )
120- .contains (Class .class .getTypeName () + "<T>" )
121- .contains ("T" );
117+ assertThat (boundType .getRawType ()).isEqualTo (Comparable .class );
118+ assertThat (typeArgument ).isEqualTo ("? super T" );
122119 }
123120
124121 @ Test
125- @ Order (10 )
122+ @ Order (9 )
126123 @ SneakyThrows
127124 @ DisplayName ("put stores provided value when current max is null" )
128125 void putStoresValueWhenCurrentMaxIsNull () {
@@ -133,7 +130,7 @@ void putStoresValueWhenCurrentMaxIsNull() {
133130 }
134131
135132 @ Test
136- @ Order (11 )
133+ @ Order (10 )
137134 @ SneakyThrows
138135 @ DisplayName ("put returns null when current max is null" )
139136 void putReturnsNullWhenCurrentMaxIsNull () {
@@ -143,7 +140,7 @@ void putReturnsNullWhenCurrentMaxIsNull() {
143140 }
144141
145142 @ Test
146- @ Order (12 )
143+ @ Order (11 )
147144 @ SneakyThrows
148145 @ DisplayName ("put stores provided value when current max is smaller than it" )
149146 void putStoresValueWhenCurrentMaxIsSmaller () {
@@ -156,7 +153,7 @@ void putStoresValueWhenCurrentMaxIsSmaller() {
156153 }
157154
158155 @ Test
159- @ Order (13 )
156+ @ Order (12 )
160157 @ SneakyThrows
161158 @ DisplayName ("put returns old max value when the provided value is greater than it" )
162159 void putReturnsOldMaxValue () {
@@ -168,7 +165,7 @@ void putReturnsOldMaxValue() {
168165 }
169166
170167 @ Test
171- @ Order (14 )
168+ @ Order (13 )
172169 @ SneakyThrows
173170 @ DisplayName ("put ignores provided value when the current max is greater than it" )
174171 void putIgnoresNewValueWhenCurrentMaxIsGreater () {
@@ -181,7 +178,7 @@ void putIgnoresNewValueWhenCurrentMaxIsGreater() {
181178 }
182179
183180 @ Test
184- @ Order (15 )
181+ @ Order (14 )
185182 @ SneakyThrows
186183 @ DisplayName ("put returns provided value when the current max is greater than it" )
187184 void putReturnsProvidedValueWhenCurrentMaxIsGreater () {
@@ -193,45 +190,67 @@ void putReturnsProvidedValueWhenCurrentMaxIsGreater() {
193190 }
194191
195192 @ Test
196- @ Order (16 )
193+ @ Order (15 )
197194 @ SneakyThrows
198- @ DisplayName ("put method is overloaded with additional Comparator param " )
195+ @ DisplayName ("put method is overloaded with additional Comparator parameter " )
199196 void putIsOverloadedWithAdditionalComparatorParam () {
200- var overloadedPutMethod = getOverloadedPutMethod ();
201- var params = overloadedPutMethod .getParameters ();
197+ HeterogeneousMaxHolder .class .getMethod ("put" , Class .class , Object .class , Comparator .class );
198+ }
199+
200+ @ Test
201+ @ Order (16 )
202+ @ DisplayName ("Overloaded put method declares one type parameter T" )
203+ void overloadedPutDeclaresOneTypeParam () {
204+ var putMethod = getOverloadedPutMethod ();
202205
203- assertThat (params [2 ].getType ()).isEqualTo (Comparator .class );
206+ var methodTypeParameters = putMethod .getTypeParameters ();
207+ assertThat (methodTypeParameters ).hasSize (1 );
204208
209+ var typeParam = putMethod .getTypeParameters ()[0 ];
210+ assertThat (typeParam .getName ()).isEqualTo ("T" );
205211 }
206212
207213 @ Test
208214 @ Order (17 )
209- @ DisplayName ("Overloaded put has simple type param 'T'" )
210- void overloadedPutHasSimpleTypeParameterT () {
211- var overloadedPutMethod = getOverloadedPutMethod ();
215+ @ DisplayName ("Overloaded put method accepts type-safe key" )
216+ void overloadedPutMethodAcceptsTypeSafeKeyParameter () {
217+ var putMethod = getOverloadedPutMethod ();
218+
219+ var typeParam = (ParameterizedType ) putMethod .getGenericParameterTypes ()[0 ];
220+ var typeArgument = typeParam .getActualTypeArguments ()[0 ];
212221
213- assertThat (overloadedPutMethod . getTypeParameters ()).hasSize ( 1 );
214- assertThat (overloadedPutMethod . getTypeParameters ()[ 0 ] .getTypeName ()).isEqualTo ("T" );
222+ assertThat (typeParam . getRawType ()).isEqualTo ( Class . class );
223+ assertThat (typeArgument .getTypeName ()).isEqualTo ("T" );
215224 }
216225
217226 @ Test
218227 @ Order (18 )
228+ @ DisplayName ("Overloaded put method accepts value of arbitrary type T" )
229+ void overloadedPutMethodAcceptsAnyValue () {
230+ var putMethod = getOverloadedPutMethod ();
231+
232+ var genericValueTypeParam = putMethod .getGenericParameterTypes ()[1 ];
233+ var actualValueTypeParm = putMethod .getParameterTypes ()[1 ];
234+
235+ assertThat (genericValueTypeParam .getTypeName ()).isEqualTo ("T" );
236+ assertThat (actualValueTypeParm ).isEqualTo (Object .class );
237+ }
238+
239+ @ Test
240+ @ Order (19 )
219241 @ SneakyThrows
220- @ DisplayName ("Overloaded put method params specify type arguments " )
221- void overloadedPutParametersSpecifyTypeArguments () {
242+ @ DisplayName ("Overloaded put method supports comparator of a super type " )
243+ void overloadedPutAcceptsComparatorOfSuperTypes () {
222244 var putMethod = HeterogeneousMaxHolder .class .getMethod ("put" , Class .class , Object .class , Comparator .class );
223- var genericParamTypeNames = Arrays .stream (putMethod .getGenericParameterTypes ())
224- .map (Type ::getTypeName )
225- .toList ();
226245
227- assertThat ( genericParamTypeNames )
228- . contains ( Class . class . getTypeName () + "<T>" )
229- . contains ( "T" )
230- . contains ( Comparator . class . getTypeName () + "< ? super T> " );
246+ var comparatorParam = ( ParameterizedType ) putMethod . getGenericParameterTypes ()[ 2 ];
247+ var comparatorTypeArgument = comparatorParam . getActualTypeArguments ()[ 0 ];
248+
249+ assertThat ( comparatorTypeArgument . getTypeName ()). isEqualTo ( " ? super T" );
231250 }
232251
233252 @ Test
234- @ Order (19 )
253+ @ Order (20 )
235254 @ SneakyThrows
236255 @ DisplayName ("Overloaded put stores provided value when current max is null" )
237256 void overloadedPutStoresValueWhenCurrentMaxIsNull () {
@@ -243,7 +262,7 @@ void overloadedPutStoresValueWhenCurrentMaxIsNull() {
243262 }
244263
245264 @ Test
246- @ Order (20 )
265+ @ Order (21 )
247266 @ SneakyThrows
248267 @ DisplayName ("Overloaded put returns null when current max is null" )
249268 void overloadedPutReturnsNullWhenCurrentMaxIsNull () {
@@ -253,7 +272,7 @@ void overloadedPutReturnsNullWhenCurrentMaxIsNull() {
253272 }
254273
255274 @ Test
256- @ Order (21 )
275+ @ Order (22 )
257276 @ SneakyThrows
258277 @ DisplayName ("Overloaded put stores provided value when current max is smaller than it" )
259278 void overloadedPutStoresValueWhenCurrentMaxIsSmaller () {
@@ -269,7 +288,7 @@ void overloadedPutStoresValueWhenCurrentMaxIsSmaller() {
269288 }
270289
271290 @ Test
272- @ Order (22 )
291+ @ Order (23 )
273292 @ SneakyThrows
274293 @ DisplayName ("Overloaded put returns old max value when the provided value is greater than it" )
275294 void overloadedPutReturnsOldMaxValue () {
@@ -284,7 +303,7 @@ void overloadedPutReturnsOldMaxValue() {
284303 }
285304
286305 @ Test
287- @ Order (23 )
306+ @ Order (24 )
288307 @ SneakyThrows
289308 @ DisplayName ("Overloaded put ignores provided value when the current max is greater than it" )
290309 void overloadedPutIgnoresNewValueWhenCurrentMaxIsGreater () {
@@ -300,7 +319,7 @@ void overloadedPutIgnoresNewValueWhenCurrentMaxIsGreater() {
300319 }
301320
302321 @ Test
303- @ Order (24 )
322+ @ Order (25 )
304323 @ SneakyThrows
305324 @ DisplayName ("Overloaded put returns provided value when the current max is greater" )
306325 void overloadedPutReturnsProvidedValueWhenCurrentMaxIsGreater () {
@@ -315,7 +334,7 @@ void overloadedPutReturnsProvidedValueWhenCurrentMaxIsGreater() {
315334 }
316335
317336 @ Test
318- @ Order (25 )
337+ @ Order (26 )
319338 @ DisplayName ("getMax method exists" )
320339 void getMaxExists () {
321340 var getMaxMethodExists = Arrays .stream (HeterogeneousMaxHolder .class .getDeclaredMethods ())
@@ -325,7 +344,7 @@ void getMaxExists() {
325344 }
326345
327346 @ Test
328- @ Order (26 )
347+ @ Order (27 )
329348 @ DisplayName ("getMax declares one simple type param 'T'" )
330349 void getMaxDeclaresOneTypeParam () {
331350 var getMaxMethod = getGetMaxMethod ();
@@ -337,7 +356,7 @@ void getMaxDeclaresOneTypeParam() {
337356 }
338357
339358 @ Test
340- @ Order (27 )
359+ @ Order (28 )
341360 @ DisplayName ("getMax has one parameter" )
342361 void getMaxHasOneParameter () {
343362 var getMaxMethod = getGetMaxMethod ();
@@ -349,7 +368,7 @@ void getMaxHasOneParameter() {
349368 }
350369
351370 @ Test
352- @ Order (28 )
371+ @ Order (29 )
353372 @ DisplayName ("getMax param specifies type arguments" )
354373 void getMaxParamSpecifyTypeArguments () {
355374 var getMaxMethod = getGetMaxMethod ();
@@ -360,7 +379,7 @@ void getMaxParamSpecifyTypeArguments() {
360379 }
361380
362381 @ Test
363- @ Order (29 )
382+ @ Order (30 )
364383 @ DisplayName ("getMax returns value when it exists" )
365384 void getMaxReturnsValueWhenItExists () {
366385 givenMaxHolderWithData (String .class , "I am maximum" );
@@ -371,7 +390,7 @@ void getMaxReturnsValueWhenItExists() {
371390 }
372391
373392 @ Test
374- @ Order (30 )
393+ @ Order (31 )
375394 @ DisplayName ("getMax returns value when it exists" )
376395 void getMaxReturnsNullWhenNoValueByGivenTypeExists () {
377396 var returnedValue = callGetMax (String .class );
@@ -380,7 +399,7 @@ void getMaxReturnsNullWhenNoValueByGivenTypeExists() {
380399 }
381400
382401 @ Test
383- @ Order (31 )
402+ @ Order (32 )
384403 @ DisplayName ("HeterogeneousMaxHolder keeps track of value one per each type" )
385404 void maxHolderKeepsTrackOfMultipleValuesPerType () {
386405 callPut (String .class , "A" );
0 commit comments