12
12
13
13
import static org .assertj .core .api .Assertions .assertThat ;
14
14
import static org .assertj .core .api .Assertions .assertThatExceptionOfType ;
15
+ import static org .junit .platform .commons .util .ClassLoaderUtils .getClassLoader ;
16
+ import static org .mockito .ArgumentMatchers .any ;
17
+ import static org .mockito .Mockito .doReturn ;
18
+ import static org .mockito .Mockito .doThrow ;
15
19
import static org .mockito .Mockito .mock ;
20
+ import static org .mockito .Mockito .never ;
21
+ import static org .mockito .Mockito .spy ;
22
+ import static org .mockito .Mockito .verify ;
16
23
import static org .mockito .Mockito .when ;
17
24
18
- import java .io .File ;
19
- import java .lang .Thread .State ;
20
25
import java .lang .reflect .Method ;
21
- import java .math .BigDecimal ;
22
- import java .math .BigInteger ;
23
- import java .net .URI ;
24
- import java .net .URL ;
25
- import java .nio .charset .Charset ;
26
- import java .nio .charset .StandardCharsets ;
27
- import java .nio .file .Path ;
28
- import java .nio .file .Paths ;
29
- import java .time .Duration ;
30
- import java .time .Instant ;
31
- import java .time .LocalDate ;
32
- import java .time .LocalDateTime ;
33
- import java .time .LocalTime ;
34
- import java .time .MonthDay ;
35
- import java .time .OffsetDateTime ;
36
- import java .time .OffsetTime ;
37
- import java .time .Period ;
38
- import java .time .Year ;
39
- import java .time .YearMonth ;
40
- import java .time .ZoneId ;
41
- import java .time .ZoneOffset ;
42
- import java .time .ZonedDateTime ;
43
- import java .util .Currency ;
44
- import java .util .Locale ;
45
- import java .util .UUID ;
46
- import java .util .concurrent .TimeUnit ;
47
26
48
27
import org .junit .jupiter .api .Test ;
49
28
import org .junit .jupiter .api .extension .ParameterContext ;
50
29
import org .junit .jupiter .params .ParameterizedTest ;
51
30
import org .junit .jupiter .params .provider .ValueSource ;
52
31
import org .junit .platform .commons .support .ReflectionSupport ;
32
+ import org .junit .platform .commons .support .conversion .ConversionException ;
53
33
import org .junit .platform .commons .test .TestClassLoader ;
54
34
55
35
/**
59
39
*/
60
40
class DefaultArgumentConverterTests {
61
41
42
+ private final DefaultArgumentConverter underTest = spy (DefaultArgumentConverter .INSTANCE );
43
+
62
44
@ Test
63
45
void isAwareOfNull () {
64
46
assertConverts (null , Object .class , null );
@@ -92,187 +74,51 @@ void isAwareOfWideningConversions() {
92
74
assertConverts (1.0f , double .class , 1.0f );
93
75
}
94
76
95
- @ Test
96
- void convertsStringsToPrimitiveTypes () {
97
- assertConverts ("true" , boolean .class , true );
98
- assertConverts ("false" , boolean .class , false );
99
- assertConverts ("o" , char .class , 'o' );
100
- assertConverts ("1" , byte .class , (byte ) 1 );
101
- assertConverts ("1_0" , byte .class , (byte ) 10 );
102
- assertConverts ("1" , short .class , (short ) 1 );
103
- assertConverts ("1_2" , short .class , (short ) 12 );
104
- assertConverts ("42" , int .class , 42 );
105
- assertConverts ("700_050_000" , int .class , 700_050_000 );
106
- assertConverts ("42" , long .class , 42L );
107
- assertConverts ("4_2" , long .class , 42L );
108
- assertConverts ("42.23" , float .class , 42.23f );
109
- assertConverts ("42.2_3" , float .class , 42.23f );
110
- assertConverts ("42.23" , double .class , 42.23 );
111
- assertConverts ("42.2_3" , double .class , 42.23 );
112
- }
113
-
114
- @ Test
115
- void convertsStringsToPrimitiveWrapperTypes () {
116
- assertConverts ("true" , Boolean .class , true );
117
- assertConverts ("false" , Boolean .class , false );
118
- assertConverts ("o" , Character .class , 'o' );
119
- assertConverts ("1" , Byte .class , (byte ) 1 );
120
- assertConverts ("1_0" , Byte .class , (byte ) 10 );
121
- assertConverts ("1" , Short .class , (short ) 1 );
122
- assertConverts ("1_2" , Short .class , (short ) 12 );
123
- assertConverts ("42" , Integer .class , 42 );
124
- assertConverts ("700_050_000" , Integer .class , 700_050_000 );
125
- assertConverts ("42" , Long .class , 42L );
126
- assertConverts ("4_2" , Long .class , 42L );
127
- assertConverts ("42.23" , Float .class , 42.23f );
128
- assertConverts ("42.2_3" , Float .class , 42.23f );
129
- assertConverts ("42.23" , Double .class , 42.23 );
130
- assertConverts ("42.2_3" , Double .class , 42.23 );
131
- }
132
-
133
77
@ ParameterizedTest (name = "[{index}] {0}" )
134
78
@ ValueSource (classes = { char .class , boolean .class , short .class , byte .class , int .class , long .class , float .class ,
135
79
double .class , void .class })
136
80
void throwsExceptionForNullToPrimitiveTypeConversion (Class <?> type ) {
137
81
assertThatExceptionOfType (ArgumentConversionException .class ) //
138
82
.isThrownBy (() -> convert (null , type )) //
139
83
.withMessage ("Cannot convert null to primitive value of type " + type .getCanonicalName ());
140
- }
141
84
142
- @ ParameterizedTest (name = "[{index}] {0}" )
143
- @ ValueSource (classes = { Boolean .class , Character .class , Short .class , Byte .class , Integer .class , Long .class ,
144
- Float .class , Double .class })
145
- void throwsExceptionWhenConvertingTheWordNullToPrimitiveWrapperType (Class <?> type ) {
146
- assertThatExceptionOfType (ArgumentConversionException .class ) //
147
- .isThrownBy (() -> convert ("null" , type )) //
148
- .withMessage ("Failed to convert String \" null\" to type " + type .getCanonicalName ());
149
- assertThatExceptionOfType (ArgumentConversionException .class ) //
150
- .isThrownBy (() -> convert ("NULL" , type )) //
151
- .withMessage ("Failed to convert String \" NULL\" to type " + type .getCanonicalName ());
85
+ verify (underTest , never ()).convert (any (), any (), any (ClassLoader .class ));
152
86
}
153
87
154
88
@ Test
155
- void throwsExceptionOnInvalidStringForPrimitiveTypes () {
89
+ void throwsExceptionForNonStringsConversion () {
156
90
assertThatExceptionOfType (ArgumentConversionException .class ) //
157
- .isThrownBy (() -> convert ("ab" , char .class )) //
158
- .withMessage ("Failed to convert String \" ab\" to type char" ) //
159
- .havingCause () //
160
- .havingCause () //
161
- .withMessage ("String must have length of 1: ab" );
91
+ .isThrownBy (() -> convert (new Enigma (), String .class )) //
92
+ .withMessage ("No built-in converter for source type %s and target type java.lang.String" ,
93
+ Enigma .class .getName ());
162
94
163
- assertThatExceptionOfType (ArgumentConversionException .class ) //
164
- .isThrownBy (() -> convert ("tru" , boolean .class )) //
165
- .withMessage ("Failed to convert String \" tru\" to type boolean" ) //
166
- .havingCause () //
167
- .havingCause () //
168
- .withMessage ("String must be 'true' or 'false' (ignoring case): tru" );
169
-
170
- assertThatExceptionOfType (ArgumentConversionException .class ) //
171
- .isThrownBy (() -> convert ("null" , boolean .class )) //
172
- .withMessage ("Failed to convert String \" null\" to type boolean" ) //
173
- .havingCause () //
174
- .havingCause () //
175
- .withMessage ("String must be 'true' or 'false' (ignoring case): null" );
176
-
177
- assertThatExceptionOfType (ArgumentConversionException .class ) //
178
- .isThrownBy (() -> convert ("NULL" , boolean .class )) //
179
- .withMessage ("Failed to convert String \" NULL\" to type boolean" ) //
180
- .havingCause () //
181
- .havingCause () //
182
- .withMessage ("String must be 'true' or 'false' (ignoring case): NULL" );
95
+ verify (underTest , never ()).convert (any (), any (), any (ClassLoader .class ));
183
96
}
184
97
185
98
@ Test
186
- void throwsExceptionWhenImplicitConverstionIsUnsupported () {
187
- assertThatExceptionOfType (ArgumentConversionException .class ) //
188
- .isThrownBy (() -> convert ("foo" , Enigma .class )) //
189
- .withMessage ("No built-in converter for source type java.lang.String and target type %s" ,
190
- Enigma .class .getName ());
99
+ void delegatesStringsConversion () {
100
+ doReturn (null ).when (underTest ).convert (any (), any (), any (ClassLoader .class ));
191
101
192
- assertThatExceptionOfType (ArgumentConversionException .class ) //
193
- .isThrownBy (() -> convert (new Enigma (), int [].class )) //
194
- .withMessage ("No built-in converter for source type %s and target type int[]" , Enigma .class .getName ());
195
-
196
- assertThatExceptionOfType (ArgumentConversionException .class ) //
197
- .isThrownBy (() -> convert (new long [] {}, int [].class )) //
198
- .withMessage ("No built-in converter for source type long[] and target type int[]" );
199
-
200
- assertThatExceptionOfType (ArgumentConversionException .class ) //
201
- .isThrownBy (() -> convert (new String [] {}, boolean .class )) //
202
- .withMessage ("No built-in converter for source type java.lang.String[] and target type boolean" );
203
-
204
- assertThatExceptionOfType (ArgumentConversionException .class ) //
205
- .isThrownBy (() -> convert (Class .class , int [].class )) //
206
- .withMessage ("No built-in converter for source type java.lang.Class and target type int[]" );
207
- }
208
-
209
- /**
210
- * @since 5.4
211
- */
212
- @ Test
213
- @ SuppressWarnings ("OctalInteger" ) // We test parsing octal integers here as well as hex.
214
- void convertsEncodedStringsToIntegralTypes () {
215
- assertConverts ("0x1f" , byte .class , (byte ) 0x1F );
216
- assertConverts ("-0x1F" , byte .class , (byte ) -0x1F );
217
- assertConverts ("010" , byte .class , (byte ) 010 );
218
-
219
- assertConverts ("0x1f00" , short .class , (short ) 0x1F00 );
220
- assertConverts ("-0x1F00" , short .class , (short ) -0x1F00 );
221
- assertConverts ("01000" , short .class , (short ) 01000 );
222
-
223
- assertConverts ("0x1f000000" , int .class , 0x1F000000 );
224
- assertConverts ("-0x1F000000" , int .class , -0x1F000000 );
225
- assertConverts ("010000000" , int .class , 010000000 );
226
-
227
- assertConverts ("0x1f000000000" , long .class , 0x1F000000000L );
228
- assertConverts ("-0x1F000000000" , long .class , -0x1F000000000L );
229
- assertConverts ("0100000000000" , long .class , 0100000000000L );
230
- }
231
-
232
- @ Test
233
- void convertsStringsToEnumConstants () {
234
- assertConverts ("DAYS" , TimeUnit .class , TimeUnit .DAYS );
235
- }
236
-
237
- // --- java.io and java.nio ------------------------------------------------
238
-
239
- @ Test
240
- void convertsStringToCharset () {
241
- assertConverts ("ISO-8859-1" , Charset .class , StandardCharsets .ISO_8859_1 );
242
- assertConverts ("UTF-8" , Charset .class , StandardCharsets .UTF_8 );
243
- }
102
+ convert ("value" , int .class );
244
103
245
- @ Test
246
- void convertsStringToFile () {
247
- assertConverts ("file" , File .class , new File ("file" ));
248
- assertConverts ("/file" , File .class , new File ("/file" ));
249
- assertConverts ("/some/file" , File .class , new File ("/some/file" ));
104
+ verify (underTest ).convert ("value" , int .class , getClassLoader (DefaultArgumentConverterTests .class ));
250
105
}
251
106
252
107
@ Test
253
- void convertsStringToPath () {
254
- assertConverts ("path" , Path .class , Paths .get ("path" ));
255
- assertConverts ("/path" , Path .class , Paths .get ("/path" ));
256
- assertConverts ("/some/path" , Path .class , Paths .get ("/some/path" ));
257
- }
108
+ void throwsExceptionForDelegatedConversionFailure () {
109
+ ConversionException exception = new ConversionException ("fail" );
110
+ doThrow (exception ).when (underTest ).convert (any (), any (), any (ClassLoader .class ));
258
111
259
- // --- java.lang -----------------------------------------------------------
112
+ assertThatExceptionOfType (ArgumentConversionException .class ) //
113
+ .isThrownBy (() -> convert ("value" , int .class )) //
114
+ .withCause (exception ) //
115
+ .withMessage (exception .getMessage ());
260
116
261
- @ Test
262
- void convertsStringToClass () {
263
- assertConverts ("java.lang.Integer" , Class .class , Integer .class );
264
- assertConverts ("java.lang.Void" , Class .class , Void .class );
265
- assertConverts ("java.lang.Thread$State" , Class .class , State .class );
266
- assertConverts ("byte" , Class .class , byte .class );
267
- assertConverts ("void" , Class .class , void .class );
268
- assertConverts ("char[]" , Class .class , char [].class );
269
- assertConverts ("java.lang.Long[][]" , Class .class , Long [][].class );
270
- assertConverts ("[[[I" , Class .class , int [][][].class );
271
- assertConverts ("[[Ljava.lang.String;" , Class .class , String [][].class );
117
+ verify (underTest ).convert ("value" , int .class , getClassLoader (DefaultArgumentConverterTests .class ));
272
118
}
273
119
274
120
@ Test
275
- void convertsStringToClassWithCustomTypeFromDifferentClassLoader () throws Exception {
121
+ void delegatesStringToClassWithCustomTypeFromDifferentClassLoaderConversion () throws Exception {
276
122
String customTypeName = Enigma .class .getName ();
277
123
try (var testClassLoader = TestClassLoader .forClasses (Enigma .class )) {
278
124
var customType = testClassLoader .loadClass (customTypeName );
@@ -281,79 +127,15 @@ void convertsStringToClassWithCustomTypeFromDifferentClassLoader() throws Except
281
127
var declaringExecutable = ReflectionSupport .findMethod (customType , "foo" ).get ();
282
128
assertThat (declaringExecutable .getDeclaringClass ().getClassLoader ()).isSameAs (testClassLoader );
283
129
130
+ doReturn (customType ).when (underTest ).convert (any (), any (), any (ClassLoader .class ));
131
+
284
132
var clazz = (Class <?>) convert (customTypeName , Class .class , parameterContext (declaringExecutable ));
285
133
assertThat (clazz ).isNotEqualTo (Enigma .class );
286
134
assertThat (clazz ).isEqualTo (customType );
287
135
assertThat (clazz .getClassLoader ()).isSameAs (testClassLoader );
288
- }
289
- }
290
-
291
- // --- java.math -----------------------------------------------------------
292
-
293
- @ Test
294
- void convertsStringToBigDecimal () {
295
- assertConverts ("123.456e789" , BigDecimal .class , new BigDecimal ("123.456e789" ));
296
- }
297
-
298
- @ Test
299
- void convertsStringToBigInteger () {
300
- assertConverts ("1234567890123456789" , BigInteger .class , new BigInteger ("1234567890123456789" ));
301
- }
302
-
303
- // --- java.net ------------------------------------------------------------
304
-
305
- @ Test
306
- void convertsStringToURI () {
307
- assertConverts ("https://docs.oracle.com/en/java/javase/12/" , URI .class ,
308
- URI .create ("https://docs.oracle.com/en/java/javase/12/" ));
309
- }
310
136
311
- @ Test
312
- void convertsStringToURL () throws Exception {
313
- assertConverts ("https://junit.org/junit5" , URL .class , URI .create ("https://junit.org/junit5" ).toURL ());
314
- }
315
-
316
- // --- java.time -----------------------------------------------------------
317
-
318
- @ Test
319
- void convertsStringsToJavaTimeInstances () {
320
- assertConverts ("PT1234.5678S" , Duration .class , Duration .ofSeconds (1234 , 567800000 ));
321
- assertConverts ("1970-01-01T00:00:00Z" , Instant .class , Instant .ofEpochMilli (0 ));
322
- assertConverts ("2017-03-14" , LocalDate .class , LocalDate .of (2017 , 3 , 14 ));
323
- assertConverts ("2017-03-14T12:34:56.789" , LocalDateTime .class ,
324
- LocalDateTime .of (2017 , 3 , 14 , 12 , 34 , 56 , 789_000_000 ));
325
- assertConverts ("12:34:56.789" , LocalTime .class , LocalTime .of (12 , 34 , 56 , 789_000_000 ));
326
- assertConverts ("--03-14" , MonthDay .class , MonthDay .of (3 , 14 ));
327
- assertConverts ("2017-03-14T12:34:56.789Z" , OffsetDateTime .class ,
328
- OffsetDateTime .of (2017 , 3 , 14 , 12 , 34 , 56 , 789_000_000 , ZoneOffset .UTC ));
329
- assertConverts ("12:34:56.789Z" , OffsetTime .class , OffsetTime .of (12 , 34 , 56 , 789_000_000 , ZoneOffset .UTC ));
330
- assertConverts ("P2M6D" , Period .class , Period .of (0 , 2 , 6 ));
331
- assertConverts ("2017" , Year .class , Year .of (2017 ));
332
- assertConverts ("2017-03" , YearMonth .class , YearMonth .of (2017 , 3 ));
333
- assertConverts ("2017-03-14T12:34:56.789Z" , ZonedDateTime .class ,
334
- ZonedDateTime .of (2017 , 3 , 14 , 12 , 34 , 56 , 789_000_000 , ZoneOffset .UTC ));
335
- assertConverts ("Europe/Berlin" , ZoneId .class , ZoneId .of ("Europe/Berlin" ));
336
- assertConverts ("+02:30" , ZoneOffset .class , ZoneOffset .ofHoursMinutes (2 , 30 ));
337
- }
338
-
339
- // --- java.util -----------------------------------------------------------
340
-
341
- @ Test
342
- void convertsStringToCurrency () {
343
- assertConverts ("JPY" , Currency .class , Currency .getInstance ("JPY" ));
344
- }
345
-
346
- @ Test
347
- @ SuppressWarnings ("deprecation" )
348
- void convertsStringToLocale () {
349
- assertConverts ("en" , Locale .class , Locale .ENGLISH );
350
- assertConverts ("en_us" , Locale .class , new Locale (Locale .US .toString ()));
351
- }
352
-
353
- @ Test
354
- void convertsStringToUUID () {
355
- var uuid = "d043e930-7b3b-48e3-bdbe-5a3ccfb833db" ;
356
- assertConverts (uuid , UUID .class , UUID .fromString (uuid ));
137
+ verify (underTest ).convert (customTypeName , Class .class , testClassLoader );
138
+ }
357
139
}
358
140
359
141
// -------------------------------------------------------------------------
@@ -364,14 +146,16 @@ private void assertConverts(Object input, Class<?> targetClass, Object expectedO
364
146
assertThat (result ) //
365
147
.describedAs (input + " --(" + targetClass .getName () + ")--> " + expectedOutput ) //
366
148
.isEqualTo (expectedOutput );
149
+
150
+ verify (underTest , never ()).convert (any (), any (), any (ClassLoader .class ));
367
151
}
368
152
369
153
private Object convert (Object input , Class <?> targetClass ) {
370
154
return convert (input , targetClass , parameterContext ());
371
155
}
372
156
373
157
private Object convert (Object input , Class <?> targetClass , ParameterContext parameterContext ) {
374
- return DefaultArgumentConverter . INSTANCE .convert (input , targetClass , parameterContext );
158
+ return underTest .convert (input , targetClass , parameterContext );
375
159
}
376
160
377
161
private static ParameterContext parameterContext () {
0 commit comments