/* * Copyright 2002-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.core.convert.converter; import java.awt.Color; import java.lang.reflect.Method; import java.math.BigDecimal; import java.math.BigInteger; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.time.ZoneId; import java.util.AbstractList; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Currency; import java.util.EnumSet; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.LinkedList; import java.util.List; import java.util.Locale; import java.util.Map; import java.util.Optional; import java.util.Properties; import java.util.Set; import java.util.TimeZone; import java.util.UUID; import java.util.stream.Stream; import org.junit.Test; import org.springframework.core.MethodParameter; import org.springframework.core.convert.ConversionFailedException; import org.springframework.core.convert.ConverterNotFoundException; import org.springframework.core.convert.TypeDescriptor; import org.springframework.core.convert.support.DefaultConversionService; import org.springframework.tests.Assume; import org.springframework.tests.TestGroup; import org.springframework.util.ClassUtils; import org.springframework.util.StopWatch; import static org.hamcrest.Matchers.*; import static org.junit.Assert.*; /** * Unit tests for {@link DefaultConversionService}. * * <p>In this package for enforcing accessibility checks to non-public classes outside * of the {@code org.springframework.core.convert.support} implementation package. * Only in such a scenario, {@code setAccessible(true)} is actually necessary. * * @author Keith Donald * @author Juergen Hoeller * @author Stephane Nicoll * @author Sam Brannen */ public class DefaultConversionServiceTests { private final DefaultConversionService conversionService = new DefaultConversionService(); @Test public void testStringToCharacter() { assertEquals(Character.valueOf('1'), conversionService.convert("1", Character.class)); } @Test public void testStringToCharacterEmptyString() { assertEquals(null, conversionService.convert("", Character.class)); } @Test(expected = ConversionFailedException.class) public void testStringToCharacterInvalidString() { conversionService.convert("invalid", Character.class); } @Test public void testCharacterToString() { assertEquals("3", conversionService.convert('3', String.class)); } @Test public void testStringToBooleanTrue() { assertEquals(true, conversionService.convert("true", Boolean.class)); assertEquals(true, conversionService.convert("on", Boolean.class)); assertEquals(true, conversionService.convert("yes", Boolean.class)); assertEquals(true, conversionService.convert("1", Boolean.class)); assertEquals(true, conversionService.convert("TRUE", Boolean.class)); assertEquals(true, conversionService.convert("ON", Boolean.class)); assertEquals(true, conversionService.convert("YES", Boolean.class)); } @Test public void testStringToBooleanFalse() { assertEquals(false, conversionService.convert("false", Boolean.class)); assertEquals(false, conversionService.convert("off", Boolean.class)); assertEquals(false, conversionService.convert("no", Boolean.class)); assertEquals(false, conversionService.convert("0", Boolean.class)); assertEquals(false, conversionService.convert("FALSE", Boolean.class)); assertEquals(false, conversionService.convert("OFF", Boolean.class)); assertEquals(false, conversionService.convert("NO", Boolean.class)); } @Test public void testStringToBooleanEmptyString() { assertEquals(null, conversionService.convert("", Boolean.class)); } @Test(expected = ConversionFailedException.class) public void testStringToBooleanInvalidString() { conversionService.convert("invalid", Boolean.class); } @Test public void testBooleanToString() { assertEquals("true", conversionService.convert(true, String.class)); } @Test public void testStringToByte() throws Exception { assertEquals(Byte.valueOf("1"), conversionService.convert("1", Byte.class)); } @Test public void testByteToString() { assertEquals("65", conversionService.convert("A".getBytes()[0], String.class)); } @Test public void testStringToShort() { assertEquals(Short.valueOf("1"), conversionService.convert("1", Short.class)); } @Test public void testShortToString() { short three = 3; assertEquals("3", conversionService.convert(three, String.class)); } @Test public void testStringToInteger() { assertEquals(Integer.valueOf("1"), conversionService.convert("1", Integer.class)); } @Test public void testIntegerToString() { assertEquals("3", conversionService.convert(3, String.class)); } @Test public void testStringToLong() { assertEquals(Long.valueOf("1"), conversionService.convert("1", Long.class)); } @Test public void testLongToString() { assertEquals("3", conversionService.convert(3L, String.class)); } @Test public void testStringToFloat() { assertEquals(Float.valueOf("1.0"), conversionService.convert("1.0", Float.class)); } @Test public void testFloatToString() { assertEquals("1.0", conversionService.convert(new Float("1.0"), String.class)); } @Test public void testStringToDouble() { assertEquals(Double.valueOf("1.0"), conversionService.convert("1.0", Double.class)); } @Test public void testDoubleToString() { assertEquals("1.0", conversionService.convert(new Double("1.0"), String.class)); } @Test public void testStringToBigInteger() { assertEquals(new BigInteger("1"), conversionService.convert("1", BigInteger.class)); } @Test public void testBigIntegerToString() { assertEquals("100", conversionService.convert(new BigInteger("100"), String.class)); } @Test public void testStringToBigDecimal() { assertEquals(new BigDecimal("1.0"), conversionService.convert("1.0", BigDecimal.class)); } @Test public void testBigDecimalToString() { assertEquals("100.00", conversionService.convert(new BigDecimal("100.00"), String.class)); } @Test public void testStringToNumber() { assertEquals(new BigDecimal("1.0"), conversionService.convert("1.0", Number.class)); } @Test public void testStringToNumberEmptyString() { assertEquals(null, conversionService.convert("", Number.class)); } @Test public void testStringToEnum() throws Exception { assertEquals(Foo.BAR, conversionService.convert("BAR", Foo.class)); } @Test public void testStringToEnumWithSubclass() throws Exception { assertEquals(SubFoo.BAZ, conversionService.convert("BAZ", SubFoo.BAR.getClass())); } @Test public void testStringToEnumEmptyString() { assertEquals(null, conversionService.convert("", Foo.class)); } @Test public void testEnumToString() { assertEquals("BAR", conversionService.convert(Foo.BAR, String.class)); } @Test public void testIntegerToEnum() throws Exception { assertEquals(Foo.BAR, conversionService.convert(0, Foo.class)); } @Test public void testIntegerToEnumWithSubclass() throws Exception { assertEquals(SubFoo.BAZ, conversionService.convert(1, SubFoo.BAR.getClass())); } @Test public void testIntegerToEnumNull() { assertEquals(null, conversionService.convert(null, Foo.class)); } @Test public void testEnumToInteger() { assertEquals(Integer.valueOf(0), conversionService.convert(Foo.BAR, Integer.class)); } @Test public void testStringToEnumSet() throws Exception { assertEquals(EnumSet.of(Foo.BAR), conversionService.convert("BAR", TypeDescriptor.valueOf(String.class), new TypeDescriptor(getClass().getField("enumSet")))); } @Test public void testStringToLocale() { assertEquals(Locale.ENGLISH, conversionService.convert("en", Locale.class)); } @Test public void testStringToCharset() { assertEquals(StandardCharsets.UTF_8, conversionService.convert("UTF-8", Charset.class)); } @Test public void testCharsetToString() { assertEquals("UTF-8", conversionService.convert(StandardCharsets.UTF_8, String.class)); } @Test public void testStringToCurrency() { assertEquals(Currency.getInstance("EUR"), conversionService.convert("EUR", Currency.class)); } @Test public void testCurrencyToString() { assertEquals("USD", conversionService.convert(Currency.getInstance("USD"), String.class)); } @Test public void testStringToString() { String str = "test"; assertSame(str, conversionService.convert(str, String.class)); } @Test public void testUuidToStringAndStringToUuid() { UUID uuid = UUID.randomUUID(); String convertToString = conversionService.convert(uuid, String.class); UUID convertToUUID = conversionService.convert(convertToString, UUID.class); assertEquals(uuid, convertToUUID); } @Test public void testNumberToNumber() { assertEquals(Long.valueOf(1), conversionService.convert(1, Long.class)); } @Test(expected = ConversionFailedException.class) public void testNumberToNumberNotSupportedNumber() { conversionService.convert(1, CustomNumber.class); } @Test public void testNumberToCharacter() { assertEquals(Character.valueOf('A'), conversionService.convert(65, Character.class)); } @Test public void testCharacterToNumber() { assertEquals(new Integer(65), conversionService.convert('A', Integer.class)); } // collection conversion @Test public void convertArrayToCollectionInterface() { List<?> result = conversionService.convert(new String[] {"1", "2", "3"}, List.class); assertEquals("1", result.get(0)); assertEquals("2", result.get(1)); assertEquals("3", result.get(2)); } @Test public void convertArrayToCollectionGenericTypeConversion() throws Exception { @SuppressWarnings("unchecked") List<Integer> result = (List<Integer>) conversionService.convert(new String[] {"1", "2", "3"}, TypeDescriptor .valueOf(String[].class), new TypeDescriptor(getClass().getDeclaredField("genericList"))); assertEquals(new Integer("1"), result.get(0)); assertEquals(new Integer("2"), result.get(1)); assertEquals(new Integer("3"), result.get(2)); } @Test public void convertArrayToStream() throws Exception { String[] source = {"1", "3", "4"}; @SuppressWarnings("unchecked") Stream<Integer> result = (Stream<Integer>) this.conversionService.convert(source, TypeDescriptor.valueOf(String[].class), new TypeDescriptor(getClass().getDeclaredField("genericStream"))); assertEquals(8, result.mapToInt((x) -> x).sum()); } @Test public void testSpr7766() throws Exception { ConverterRegistry registry = (conversionService); registry.addConverter(new ColorConverter()); @SuppressWarnings("unchecked") List<Color> colors = (List<Color>) conversionService.convert(new String[] {"ffffff", "#000000"}, TypeDescriptor.valueOf(String[].class), new TypeDescriptor(new MethodParameter(getClass().getMethod("handlerMethod", List.class), 0))); assertEquals(2, colors.size()); assertEquals(Color.WHITE, colors.get(0)); assertEquals(Color.BLACK, colors.get(1)); } @Test public void convertArrayToCollectionImpl() { LinkedList<?> result = conversionService.convert(new String[] {"1", "2", "3"}, LinkedList.class); assertEquals("1", result.get(0)); assertEquals("2", result.get(1)); assertEquals("3", result.get(2)); } @Test(expected = ConversionFailedException.class) public void convertArrayToAbstractCollection() { conversionService.convert(new String[]{"1", "2", "3"}, AbstractList.class); } public static enum FooEnum { BAR, BAZ } @Test public void convertArrayToString() { String result = conversionService.convert(new String[] {"1", "2", "3"}, String.class); assertEquals("1,2,3", result); } @Test public void convertArrayToStringWithElementConversion() { String result = conversionService.convert(new Integer[] {1, 2, 3}, String.class); assertEquals("1,2,3", result); } @Test public void convertEmptyArrayToString() { String result = conversionService.convert(new String[0], String.class); assertEquals("", result); } @Test public void convertStringToArray() { String[] result = conversionService.convert("1,2,3", String[].class); assertEquals(3, result.length); assertEquals("1", result[0]); assertEquals("2", result[1]); assertEquals("3", result[2]); } @Test public void convertStringToArrayWithElementConversion() { Integer[] result = conversionService.convert("1,2,3", Integer[].class); assertEquals(3, result.length); assertEquals(new Integer(1), result[0]); assertEquals(new Integer(2), result[1]); assertEquals(new Integer(3), result[2]); } @Test public void convertStringToPrimitiveArrayWithElementConversion() { int[] result = conversionService.convert("1,2,3", int[].class); assertEquals(3, result.length); assertEquals(1, result[0]); assertEquals(2, result[1]); assertEquals(3, result[2]); } @Test public void convertEmptyStringToArray() { String[] result = conversionService.convert("", String[].class); assertEquals(0, result.length); } @Test public void convertArrayToObject() { Object[] array = new Object[] {3L}; Object result = conversionService.convert(array, Long.class); assertEquals(3L, result); } @Test public void convertArrayToObjectWithElementConversion() { String[] array = new String[] {"3"}; Integer result = conversionService.convert(array, Integer.class); assertEquals(new Integer(3), result); } @Test public void convertArrayToObjectAssignableTargetType() { Long[] array = new Long[] {3L}; Long[] result = (Long[]) conversionService.convert(array, Object.class); assertArrayEquals(array, result); } @Test public void convertObjectToArray() { Object[] result = conversionService.convert(3L, Object[].class); assertEquals(1, result.length); assertEquals(3L, result[0]); } @Test public void convertObjectToArrayWithElementConversion() { Integer[] result = conversionService.convert(3L, Integer[].class); assertEquals(1, result.length); assertEquals(new Integer(3), result[0]); } @Test public void convertCollectionToArray() { List<String> list = new ArrayList<>(); list.add("1"); list.add("2"); list.add("3"); String[] result = conversionService.convert(list, String[].class); assertEquals("1", result[0]); assertEquals("2", result[1]); assertEquals("3", result[2]); } @Test public void convertCollectionToArrayWithElementConversion() { List<String> list = new ArrayList<>(); list.add("1"); list.add("2"); list.add("3"); Integer[] result = conversionService.convert(list, Integer[].class); assertEquals(new Integer(1), result[0]); assertEquals(new Integer(2), result[1]); assertEquals(new Integer(3), result[2]); } @Test public void convertCollectionToString() { List<String> list = Arrays.asList("foo", "bar"); String result = conversionService.convert(list, String.class); assertEquals("foo,bar", result); } @Test public void convertCollectionToStringWithElementConversion() throws Exception { List<Integer> list = Arrays.asList(3, 5); String result = (String) conversionService.convert(list, new TypeDescriptor(getClass().getField("genericList")), TypeDescriptor.valueOf(String.class)); assertEquals("3,5", result); } @Test @SuppressWarnings("rawtypes") public void convertStringToCollection() { List result = conversionService.convert("1,2,3", List.class); assertEquals(3, result.size()); assertEquals("1", result.get(0)); assertEquals("2", result.get(1)); assertEquals("3", result.get(2)); } @Test @SuppressWarnings("rawtypes") public void convertStringToCollectionWithElementConversion() throws Exception { List result = (List) conversionService.convert("1,2,3", TypeDescriptor.valueOf(String.class), new TypeDescriptor(getClass().getField("genericList"))); assertEquals(3, result.size()); assertEquals(1, result.get(0)); assertEquals(2, result.get(1)); assertEquals(3, result.get(2)); } @Test @SuppressWarnings("rawtypes") public void convertEmptyStringToCollection() { Collection result = conversionService.convert("", Collection.class); assertEquals(0, result.size()); } @Test public void convertCollectionToObject() { List<Long> list = Collections.singletonList(3L); Long result = conversionService.convert(list, Long.class); assertEquals(new Long(3), result); } @Test public void convertCollectionToObjectWithElementConversion() { List<String> list = Collections.singletonList("3"); Integer result = conversionService.convert(list, Integer.class); assertEquals(new Integer(3), result); } @Test public void convertCollectionToObjectAssignableTarget() throws Exception { Collection<String> source = new ArrayList<>(); source.add("foo"); Object result = conversionService.convert(source, new TypeDescriptor(getClass().getField("assignableTarget"))); assertEquals(source, result); } @Test @SuppressWarnings("rawtypes") public void convertCollectionToObjectWithCustomConverter() throws Exception { List<String> source = new ArrayList<>(); source.add("A"); source.add("B"); conversionService.addConverter(new Converter<List, ListWrapper>() { @Override public ListWrapper convert(List source) { return new ListWrapper(source); } }); ListWrapper result = conversionService.convert(source, ListWrapper.class); assertSame(source, result.getList()); } @Test @SuppressWarnings("rawtypes") public void convertObjectToCollection() { List result = conversionService.convert(3L, List.class); assertEquals(1, result.size()); assertEquals(3L, result.get(0)); } @Test public void convertObjectToCollectionWithElementConversion() throws Exception { @SuppressWarnings("unchecked") List<Integer> result = (List<Integer>) conversionService.convert(3L, TypeDescriptor.valueOf(Long.class), new TypeDescriptor(getClass().getField("genericList"))); assertEquals(1, result.size()); assertEquals(new Integer(3), result.get(0)); } @Test public void convertArrayToArray() { Integer[] result = conversionService.convert(new String[] {"1", "2", "3"}, Integer[].class); assertEquals(new Integer(1), result[0]); assertEquals(new Integer(2), result[1]); assertEquals(new Integer(3), result[2]); } @Test public void convertArrayToPrimitiveArray() { int[] result = conversionService.convert(new String[] {"1", "2", "3"}, int[].class); assertEquals(1, result[0]); assertEquals(2, result[1]); assertEquals(3, result[2]); } @Test public void convertArrayToWrapperArray() { byte[] byteArray = new byte[] {1, 2, 3}; Byte[] converted = conversionService.convert(byteArray, Byte[].class); assertThat(converted, equalTo(new Byte[]{1, 2, 3})); } @Test public void convertArrayToArrayAssignable() { int[] result = conversionService.convert(new int[] {1, 2, 3}, int[].class); assertEquals(1, result[0]); assertEquals(2, result[1]); assertEquals(3, result[2]); } @Test public void convertListOfNonStringifiable() { List<Object> list = Arrays.asList(new TestEntity(1L), new TestEntity(2L)); assertTrue(conversionService.canConvert(list.getClass(), String.class)); try { conversionService.convert(list, String.class); } catch (ConversionFailedException ex) { assertTrue(ex.getMessage().contains(list.getClass().getName())); assertTrue(ex.getCause() instanceof ConverterNotFoundException); assertTrue(ex.getCause().getMessage().contains(TestEntity.class.getName())); } } @Test public void convertListOfStringToString() { List<String> list = Arrays.asList("Foo", "Bar"); assertTrue(conversionService.canConvert(list.getClass(), String.class)); String result = conversionService.convert(list, String.class); assertEquals("Foo,Bar", result); } @Test public void convertListOfListToString() { List<String> list1 = Arrays.asList("Foo", "Bar"); List<String> list2 = Arrays.asList("Baz", "Boop"); List<List<String>> list = Arrays.asList(list1, list2); assertTrue(conversionService.canConvert(list.getClass(), String.class)); String result = conversionService.convert(list, String.class); assertEquals("Foo,Bar,Baz,Boop", result); } @Test public void convertCollectionToCollection() throws Exception { Set<String> foo = new LinkedHashSet<>(); foo.add("1"); foo.add("2"); foo.add("3"); @SuppressWarnings("unchecked") List<Integer> bar = (List<Integer>) conversionService.convert(foo, TypeDescriptor.forObject(foo), new TypeDescriptor(getClass().getField("genericList"))); assertEquals(new Integer(1), bar.get(0)); assertEquals(new Integer(2), bar.get(1)); assertEquals(new Integer(3), bar.get(2)); } @Test public void convertCollectionToCollectionNull() throws Exception { @SuppressWarnings("unchecked") List<Integer> bar = (List<Integer>) conversionService.convert(null, TypeDescriptor.valueOf(LinkedHashSet.class), new TypeDescriptor(getClass().getField("genericList"))); assertNull(bar); } @Test @SuppressWarnings("rawtypes") public void convertCollectionToCollectionNotGeneric() throws Exception { Set<String> foo = new LinkedHashSet<>(); foo.add("1"); foo.add("2"); foo.add("3"); List bar = (List) conversionService.convert(foo, TypeDescriptor.valueOf(LinkedHashSet.class), TypeDescriptor .valueOf(List.class)); assertEquals("1", bar.get(0)); assertEquals("2", bar.get(1)); assertEquals("3", bar.get(2)); } @Test @SuppressWarnings({"unchecked", "rawtypes"}) public void convertCollectionToCollectionSpecialCaseSourceImpl() throws Exception { Map map = new LinkedHashMap(); map.put("1", "1"); map.put("2", "2"); map.put("3", "3"); Collection values = map.values(); List<Integer> bar = (List<Integer>) conversionService.convert(values, TypeDescriptor.forObject(values), new TypeDescriptor(getClass().getField("genericList"))); assertEquals(3, bar.size()); assertEquals(new Integer(1), bar.get(0)); assertEquals(new Integer(2), bar.get(1)); assertEquals(new Integer(3), bar.get(2)); } @Test public void collection() { List<String> strings = new ArrayList<>(); strings.add("3"); strings.add("9"); @SuppressWarnings("unchecked") List<Integer> integers = (List<Integer>) conversionService.convert(strings, TypeDescriptor.collection(List.class, TypeDescriptor.valueOf(Integer.class))); assertEquals(new Integer(3), integers.get(0)); assertEquals(new Integer(9), integers.get(1)); } @Test public void convertMapToMap() throws Exception { Map<String, String> foo = new HashMap<>(); foo.put("1", "BAR"); foo.put("2", "BAZ"); @SuppressWarnings("unchecked") Map<Integer, FooEnum> map = (Map<Integer, FooEnum>) conversionService.convert(foo, TypeDescriptor.forObject(foo), new TypeDescriptor(getClass().getField("genericMap"))); assertEquals(FooEnum.BAR, map.get(1)); assertEquals(FooEnum.BAZ, map.get(2)); } @Test @SuppressWarnings("rawtypes") public void convertHashMapValuesToList() { Map<String, Integer> hashMap = new LinkedHashMap<>(); hashMap.put("1", 1); hashMap.put("2", 2); List converted = conversionService.convert(hashMap.values(), List.class); assertEquals(Arrays.asList(1, 2), converted); } @Test public void map() { Map<String, String> strings = new HashMap<>(); strings.put("3", "9"); strings.put("6", "31"); @SuppressWarnings("unchecked") Map<Integer, Integer> integers = (Map<Integer, Integer>) conversionService.convert(strings, TypeDescriptor.map(Map.class, TypeDescriptor.valueOf(Integer.class), TypeDescriptor.valueOf(Integer.class))); assertEquals(new Integer(9), integers.get(3)); assertEquals(new Integer(31), integers.get(6)); } @Test public void convertPropertiesToString() { Properties foo = new Properties(); foo.setProperty("1", "BAR"); foo.setProperty("2", "BAZ"); String result = conversionService.convert(foo, String.class); assertTrue(result.contains("1=BAR")); assertTrue(result.contains("2=BAZ")); } @Test public void convertStringToProperties() { Properties result = conversionService.convert("a=b\nc=2\nd=", Properties.class); assertEquals(3, result.size()); assertEquals("b", result.getProperty("a")); assertEquals("2", result.getProperty("c")); assertEquals("", result.getProperty("d")); } @Test public void convertStringToPropertiesWithSpaces() { Properties result = conversionService.convert(" foo=bar\n bar=baz\n baz=boop", Properties.class); assertEquals("bar", result.get("foo")); assertEquals("baz", result.get("bar")); assertEquals("boop", result.get("baz")); } // generic object conversion @Test public void convertObjectToStringWithValueOfMethodPresentUsingToString() { ISBN.reset(); assertEquals("123456789", conversionService.convert(new ISBN("123456789"), String.class)); assertEquals("constructor invocations", 1, ISBN.constructorCount); assertEquals("valueOf() invocations", 0, ISBN.valueOfCount); assertEquals("toString() invocations", 1, ISBN.toStringCount); } @Test public void convertObjectToObjectUsingValueOfMethod() { ISBN.reset(); assertEquals(new ISBN("123456789"), conversionService.convert("123456789", ISBN.class)); assertEquals("valueOf() invocations", 1, ISBN.valueOfCount); // valueOf() invokes the constructor assertEquals("constructor invocations", 2, ISBN.constructorCount); assertEquals("toString() invocations", 0, ISBN.toStringCount); } @Test public void convertObjectToStringUsingToString() { SSN.reset(); assertEquals("123456789", conversionService.convert(new SSN("123456789"), String.class)); assertEquals("constructor invocations", 1, SSN.constructorCount); assertEquals("toString() invocations", 1, SSN.toStringCount); } @Test public void convertObjectToObjectUsingObjectConstructor() { SSN.reset(); assertEquals(new SSN("123456789"), conversionService.convert("123456789", SSN.class)); assertEquals("constructor invocations", 2, SSN.constructorCount); assertEquals("toString() invocations", 0, SSN.toStringCount); } @Test public void convertStringToTimezone() { assertEquals("GMT+02:00", conversionService.convert("GMT+2", TimeZone.class).getID()); } @Test public void convertObjectToStringWithJavaTimeOfMethodPresent() { assertTrue(conversionService.convert(ZoneId.of("GMT+1"), String.class).startsWith("GMT+")); } @Test public void convertObjectToStringNotSupported() { assertFalse(conversionService.canConvert(TestEntity.class, String.class)); } @Test public void convertObjectToObjectWithJavaTimeOfMethod() { assertEquals(ZoneId.of("GMT+1"), conversionService.convert("GMT+1", ZoneId.class)); } @Test(expected = ConverterNotFoundException.class) public void convertObjectToObjectNoValueOfMethodOrConstructor() { conversionService.convert(new Long(3), SSN.class); } @Test public void convertObjectToObjectFinderMethod() { TestEntity e = conversionService.convert(1L, TestEntity.class); assertEquals(new Long(1), e.getId()); } @Test public void convertObjectToObjectFinderMethodWithNull() { TestEntity entity = (TestEntity) conversionService.convert(null, TypeDescriptor.valueOf(String.class), TypeDescriptor.valueOf(TestEntity.class)); assertNull(entity); } @Test public void convertObjectToObjectFinderMethodWithIdConversion() { TestEntity entity = conversionService.convert("1", TestEntity.class); assertEquals(new Long(1), entity.getId()); } @Test public void convertCharArrayToString() throws Exception { String converted = conversionService.convert(new char[] {'a', 'b', 'c'}, String.class); assertThat(converted, equalTo("a,b,c")); } @Test public void convertStringToCharArray() throws Exception { char[] converted = conversionService.convert("a,b,c", char[].class); assertThat(converted, equalTo(new char[]{'a', 'b', 'c'})); } @Test public void convertStringToCustomCharArray() throws Exception { conversionService.addConverter(new Converter<String, char[]>() { @Override public char[] convert(String source) { return source.toCharArray(); } }); char[] converted = conversionService.convert("abc", char[].class); assertThat(converted, equalTo(new char[] {'a', 'b', 'c'})); } @Test @SuppressWarnings("unchecked") public void multidimensionalArrayToListConversionShouldConvertEntriesCorrectly() { String[][] grid = new String[][] {new String[] {"1", "2", "3", "4"}, new String[] {"5", "6", "7", "8"}, new String[] {"9", "10", "11", "12"}}; List<String[]> converted = conversionService.convert(grid, List.class); String[][] convertedBack = conversionService.convert(converted, String[][].class); assertArrayEquals(grid, convertedBack); } @Test public void convertCannotOptimizeArray() { conversionService.addConverter(new Converter<Byte, Byte>() { @Override public Byte convert(Byte source) { return (byte) (source + 1); } }); byte[] byteArray = new byte[] {1, 2, 3}; byte[] converted = conversionService.convert(byteArray, byte[].class); assertNotSame(byteArray, converted); assertTrue(Arrays.equals(new byte[] {2, 3, 4}, converted)); } @Test @SuppressWarnings("unchecked") public void convertObjectToOptional() { Method method = ClassUtils.getMethod(TestEntity.class, "handleOptionalValue", Optional.class); MethodParameter parameter = new MethodParameter(method, 0); TypeDescriptor descriptor = new TypeDescriptor(parameter); Object actual = conversionService.convert("1,2,3", TypeDescriptor.valueOf(String.class), descriptor); assertEquals(Optional.class, actual.getClass()); assertEquals(Arrays.asList(1, 2, 3), ((Optional<List<Integer>>) actual).get()); } @Test public void convertObjectToOptionalNull() { assertSame(Optional.empty(), conversionService.convert(null, TypeDescriptor.valueOf(Object.class), TypeDescriptor.valueOf(Optional.class))); assertSame(Optional.empty(), conversionService.convert(null, Optional.class)); } @Test public void convertExistingOptional() { assertSame(Optional.empty(), conversionService.convert(Optional.empty(), TypeDescriptor.valueOf(Object.class), TypeDescriptor.valueOf(Optional.class))); assertSame(Optional.empty(), conversionService.convert(Optional.empty(), Optional.class)); } @Test public void testPerformance1() { Assume.group(TestGroup.PERFORMANCE); StopWatch watch = new StopWatch("integer->string conversionPerformance"); watch.start("convert 4,000,000 with conversion service"); for (int i = 0; i < 4000000; i++) { conversionService.convert(3, String.class); } watch.stop(); watch.start("convert 4,000,000 manually"); for (int i = 0; i < 4000000; i++) { new Integer(3).toString(); } watch.stop(); // System.out.println(watch.prettyPrint()); } // test fields and helpers public List<Integer> genericList = new ArrayList<>(); public Stream<Integer> genericStream; public Map<Integer, FooEnum> genericMap = new HashMap<>(); public EnumSet<Foo> enumSet; public Object assignableTarget; public void handlerMethod(List<Color> color) { } public enum Foo { BAR, BAZ } public enum SubFoo { BAR { @Override String s() { return "x"; } }, BAZ { @Override String s() { return "y"; } }; abstract String s(); } public class ColorConverter implements Converter<String, Color> { @Override public Color convert(String source) { if (!source.startsWith("#")) { source = "#" + source; } return Color.decode(source); } } @SuppressWarnings("serial") public static class CustomNumber extends Number { @Override public double doubleValue() { return 0; } @Override public float floatValue() { return 0; } @Override public int intValue() { return 0; } @Override public long longValue() { return 0; } } public static class TestEntity { private Long id; public TestEntity(Long id) { this.id = id; } public Long getId() { return id; } public static TestEntity findTestEntity(Long id) { return new TestEntity(id); } public void handleOptionalValue(Optional<List<Integer>> value) { } } private static class ListWrapper { private List<?> list; public ListWrapper(List<?> list) { this.list = list; } public List<?> getList() { return list; } } private static class SSN { static int constructorCount = 0; static int toStringCount = 0; static void reset() { constructorCount = 0; toStringCount = 0; } private final String value; public SSN(String value) { constructorCount++; this.value = value; } @Override public boolean equals(Object o) { if (!(o instanceof SSN)) { return false; } SSN ssn = (SSN) o; return this.value.equals(ssn.value); } @Override public int hashCode() { return value.hashCode(); } @Override public String toString() { toStringCount++; return value; } } private static class ISBN { static int constructorCount = 0; static int toStringCount = 0; static int valueOfCount = 0; static void reset() { constructorCount = 0; toStringCount = 0; valueOfCount = 0; } private final String value; public ISBN(String value) { constructorCount++; this.value = value; } @Override public boolean equals(Object o) { if (!(o instanceof ISBN)) { return false; } ISBN isbn = (ISBN) o; return this.value.equals(isbn.value); } @Override public int hashCode() { return value.hashCode(); } @Override public String toString() { toStringCount++; return value; } @SuppressWarnings("unused") public static ISBN valueOf(String value) { valueOfCount++; return new ISBN(value); } } }