1212
1313import static org .assertj .core .api .Assertions .assertThat ;
1414import 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 ;
1519import 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 ;
1623import static org .mockito .Mockito .when ;
1724
18- import java .io .File ;
19- import java .lang .Thread .State ;
2025import 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 ;
4726
4827import org .junit .jupiter .api .Test ;
4928import org .junit .jupiter .api .extension .ParameterContext ;
5029import org .junit .jupiter .params .ParameterizedTest ;
5130import org .junit .jupiter .params .provider .ValueSource ;
5231import org .junit .platform .commons .support .ReflectionSupport ;
32+ import org .junit .platform .commons .support .conversion .ConversionException ;
5333import org .junit .platform .commons .test .TestClassLoader ;
5434
5535/**
5939 */
6040class DefaultArgumentConverterTests {
6141
42+ private final DefaultArgumentConverter underTest = spy (DefaultArgumentConverter .INSTANCE );
43+
6244 @ Test
6345 void isAwareOfNull () {
6446 assertConverts (null , Object .class , null );
@@ -92,187 +74,51 @@ void isAwareOfWideningConversions() {
9274 assertConverts (1.0f , double .class , 1.0f );
9375 }
9476
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-
13377 @ ParameterizedTest (name = "[{index}] {0}" )
13478 @ ValueSource (classes = { char .class , boolean .class , short .class , byte .class , int .class , long .class , float .class ,
13579 double .class , void .class })
13680 void throwsExceptionForNullToPrimitiveTypeConversion (Class <?> type ) {
13781 assertThatExceptionOfType (ArgumentConversionException .class ) //
13882 .isThrownBy (() -> convert (null , type )) //
13983 .withMessage ("Cannot convert null to primitive value of type " + type .getCanonicalName ());
140- }
14184
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 ));
15286 }
15387
15488 @ Test
155- void throwsExceptionOnInvalidStringForPrimitiveTypes () {
89+ void throwsExceptionForNonStringsConversion () {
15690 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" );
162-
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" );
183- }
184-
185- @ 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" ,
91+ .isThrownBy (() -> convert (new Enigma (), String .class )) //
92+ .withMessage ("No built-in converter for source type %s and target type java.lang.String" ,
19093 Enigma .class .getName ());
19194
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 );
95+ verify (underTest , never ()).convert (any (), any (), any (ClassLoader .class ));
23096 }
23197
23298 @ Test
233- void convertsStringsToEnumConstants () {
234- assertConverts ("DAYS" , TimeUnit .class , TimeUnit .DAYS );
235- }
236-
237- // --- java.io and java.nio ------------------------------------------------
99+ void delegatesStringsConversion () {
100+ doReturn (null ).when (underTest ).convert (any (), any (), any (ClassLoader .class ));
238101
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 );
244103
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 ));
250105 }
251106
252107 @ 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 ));
258111
259- // --- java.lang -----------------------------------------------------------
112+ assertThatExceptionOfType (ArgumentConversionException .class ) //
113+ .isThrownBy (() -> convert ("value" , int .class )) //
114+ .withCause (exception ) //
115+ .withMessage (exception .getMessage ());
260116
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 ));
272118 }
273119
274120 @ Test
275- void convertsStringToClassWithCustomTypeFromDifferentClassLoader () throws Exception {
121+ void delegatesStringToClassWithCustomTypeFromDifferentClassLoaderConversion () throws Exception {
276122 String customTypeName = Enigma .class .getName ();
277123 try (var testClassLoader = TestClassLoader .forClasses (Enigma .class )) {
278124 var customType = testClassLoader .loadClass (customTypeName );
@@ -281,79 +127,15 @@ void convertsStringToClassWithCustomTypeFromDifferentClassLoader() throws Except
281127 var declaringExecutable = ReflectionSupport .findMethod (customType , "foo" ).get ();
282128 assertThat (declaringExecutable .getDeclaringClass ().getClassLoader ()).isSameAs (testClassLoader );
283129
130+ doReturn (customType ).when (underTest ).convert (any (), any (), any (ClassLoader .class ));
131+
284132 var clazz = (Class <?>) convert (customTypeName , Class .class , parameterContext (declaringExecutable ));
285133 assertThat (clazz ).isNotEqualTo (Enigma .class );
286134 assertThat (clazz ).isEqualTo (customType );
287135 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- }
310136
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+ }
357139 }
358140
359141 // -------------------------------------------------------------------------
@@ -364,14 +146,16 @@ private void assertConverts(Object input, Class<?> targetClass, Object expectedO
364146 assertThat (result ) //
365147 .describedAs (input + " --(" + targetClass .getName () + ")--> " + expectedOutput ) //
366148 .isEqualTo (expectedOutput );
149+
150+ verify (underTest , never ()).convert (any (), any (), any (ClassLoader .class ));
367151 }
368152
369153 private Object convert (Object input , Class <?> targetClass ) {
370154 return convert (input , targetClass , parameterContext ());
371155 }
372156
373157 private Object convert (Object input , Class <?> targetClass , ParameterContext parameterContext ) {
374- return DefaultArgumentConverter . INSTANCE .convert (input , targetClass , parameterContext );
158+ return underTest .convert (input , targetClass , parameterContext );
375159 }
376160
377161 private static ParameterContext parameterContext () {
0 commit comments