org.jtransfo.internal.ConverterHelperTest.java Source code

Java tutorial

Introduction

Here is the source code for org.jtransfo.internal.ConverterHelperTest.java

Source

/*
 * This file is part of jTransfo, a library for converting to and from transfer objects.
 * Copyright (c) PROGS bvba, Belgium
 *
 * The program is available in open source according to the Apache License, Version 2.0.
 * For full licensing details, see LICENSE.txt in the project root.
 */

package org.jtransfo.internal;

import org.jtransfo.JTransfoException;
import org.jtransfo.MapOnly;
import org.jtransfo.MappedBy;
import org.jtransfo.Named;
import org.jtransfo.NoConversionTypeConverter;
import org.jtransfo.ToConverter;
import org.jtransfo.TypeConverter;
import org.jtransfo.object.AddressDomain;
import org.jtransfo.object.FaultyExtendedTo;
import org.jtransfo.object.PersonDomain;
import org.jtransfo.object.PersonTransitiveTo;
import org.jtransfo.object.SimpleExtendedDomain;
import org.jtransfo.object.SimpleExtendedTo;
import org.jtransfo.object.TaggedPersonTo;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.springframework.test.util.ReflectionTestUtils;

import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Map;

import static org.fest.assertions.Assertions.assertThat;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

/**
 * Test for {@link ConverterHelper}.
 */
public class ConverterHelperTest {

    private ConverterHelper converterHelper;

    @Mock
    private ReflectionHelper reflectionHelper;

    @Rule
    public ExpectedException exception = ExpectedException.none();

    @Before
    public void setUp() throws Exception {
        MockitoAnnotations.initMocks(this);

        converterHelper = new ConverterHelper();

        ReflectionTestUtils.setField(converterHelper, "reflectionHelper", reflectionHelper);
    }

    @Test
    public void testFindField() throws Exception {
        List<SyntheticField> fields = new ArrayList<SyntheticField>();
        SyntheticField f1 = new SimpleSyntheticField(SimpleExtendedDomain.class.getDeclaredField("b"));
        SyntheticField f2 = new SimpleSyntheticField(SimpleExtendedDomain.class.getDeclaredField("c"));
        fields.add(f1);
        fields.add(f2);

        SyntheticField[] res;
        res = converterHelper.findField(fields, "c", new String[0], SimpleExtendedDomain.class, false);
        assertThat(res[0]).isEqualTo(f2);

        exception.expect(JTransfoException.class);
        exception.expectMessage("Cannot find getter from [getBla, isBla, hasBla] on class "
                + "org.jtransfo.object.SimpleExtendedDomain.");

        converterHelper.findField(fields, "bla", new String[0], SimpleExtendedDomain.class, false);
    }

    @Test
    public void testFindFieldTransitive() throws Exception {
        List<SyntheticField> fields = new ArrayList<SyntheticField>();
        SyntheticField f1 = new SimpleSyntheticField(PersonDomain.class.getDeclaredField("name"));
        SyntheticField f2 = new SimpleSyntheticField(PersonDomain.class.getDeclaredField("address"));
        fields.add(f1);
        fields.add(f2);
        SyntheticField f3 = new SimpleSyntheticField(AddressDomain.class.getDeclaredField("id"));
        when(reflectionHelper.getSyntheticFields(any(Class.class))).thenReturn(Collections.singletonList(f3));

        SyntheticField[] res;
        res = converterHelper.findField(fields, "id", new String[] { "address" }, PersonDomain.class, false);
        assertThat(res).hasSize(2);
        assertThat(res[0]).isEqualTo(f2);
        assertThat(res[1]).isEqualTo(f3);

        exception.expect(JTransfoException.class);
        exception.expectMessage(
                "Cannot find getter from [getBla, isBla, hasBla] on " + "class org.jtransfo.object.PersonDomain.");

        converterHelper.findField(fields, "id", new String[] { "bla" }, PersonDomain.class, false);
    }

    @Test
    public void testGetDeclaredTypeConverterNull() throws Exception {
        assertThat(converterHelper.getDeclaredTypeConverter(null)).isNull();
    }

    @Test
    public void testGetDeclaredTypeConverterDefaults() throws Exception {
        MappedBy mappedBy = mock(MappedBy.class);
        when(mappedBy.typeConverterClass()).thenReturn(MappedBy.DefaultTypeConverter.class);
        when(mappedBy.typeConverter()).thenReturn(MappedBy.DEFAULT_TYPE_CONVERTER);
        when(mappedBy.field()).thenReturn(MappedBy.DEFAULT_FIELD);

        assertThat(converterHelper.getDeclaredTypeConverter(mappedBy)).isNull();
    }

    @Test
    public void testGetDeclaredTypeConverterAsClass() throws Exception {
        MappedBy mappedBy = mock(MappedBy.class);
        when(mappedBy.typeConverterClass()).thenReturn(NoConversionTypeConverter.class);
        when(mappedBy.typeConverter()).thenReturn(MappedBy.DEFAULT_TYPE_CONVERTER);
        when(mappedBy.field()).thenReturn(MappedBy.DEFAULT_FIELD);
        when(reflectionHelper.newInstance(NoConversionTypeConverter.class.getName()))
                .thenReturn(new NoConversionTypeConverter());

        TypeConverter res = converterHelper.getDeclaredTypeConverter(mappedBy);

        assertThat(res).isInstanceOf(NoConversionTypeConverter.class);

        TypeConverter res2 = converterHelper.getDeclaredTypeConverter(mappedBy);

        assertThat(res2 == res).isTrue(); // instance needs to be cached and reused
    }

    @Test
    public void testGetDeclaredTypeConverterAsName() throws Exception {
        MappedBy mappedBy = mock(MappedBy.class);
        when(mappedBy.typeConverterClass()).thenReturn(MappedBy.DefaultTypeConverter.class);
        when(mappedBy.typeConverter()).thenReturn(NoConversionTypeConverter.class.getName());
        when(mappedBy.field()).thenReturn(MappedBy.DEFAULT_FIELD);
        when(reflectionHelper.newInstance(NoConversionTypeConverter.class.getName()))
                .thenReturn(new NoConversionTypeConverter());

        TypeConverter res = converterHelper.getDeclaredTypeConverter(mappedBy);

        assertThat(res).isInstanceOf(NoConversionTypeConverter.class);
    }

    @Test
    public void testGetDeclaredTypeConverterCnfe() throws Exception {
        MappedBy mappedBy = mock(MappedBy.class);
        when(mappedBy.typeConverterClass()).thenReturn(MappedBy.DefaultTypeConverter.class);
        when(mappedBy.typeConverter()).thenReturn(NoConversionTypeConverter.class.getName());
        when(mappedBy.field()).thenReturn(MappedBy.DEFAULT_FIELD);
        when(reflectionHelper.newInstance(NoConversionTypeConverter.class.getName()))
                .thenThrow(new ClassNotFoundException());

        exception.expect(JTransfoException.class);
        exception.expectMessage(
                "Declared TypeConverter class org.jtransfo.NoConversionTypeConverter cannot be found.");
        converterHelper.getDeclaredTypeConverter(mappedBy);
    }

    @Test
    public void testGetDeclaredTypeConverterIe() throws Exception {
        MappedBy mappedBy = mock(MappedBy.class);
        when(mappedBy.typeConverterClass()).thenReturn(MappedBy.DefaultTypeConverter.class);
        when(mappedBy.typeConverter()).thenReturn(NoConversionTypeConverter.class.getName());
        when(mappedBy.field()).thenReturn(MappedBy.DEFAULT_FIELD);
        when(reflectionHelper.newInstance(NoConversionTypeConverter.class.getName()))
                .thenThrow(new InstantiationException());

        exception.expect(JTransfoException.class);
        exception.expectMessage(
                "Declared TypeConverter class org.jtransfo.NoConversionTypeConverter cannot be instantiated.");
        converterHelper.getDeclaredTypeConverter(mappedBy);
    }

    @Test
    public void testGetDeclaredTypeConverterIae() throws Exception {
        MappedBy mappedBy = mock(MappedBy.class);
        when(mappedBy.typeConverterClass()).thenReturn(MappedBy.DefaultTypeConverter.class);
        when(mappedBy.typeConverter()).thenReturn(NoConversionTypeConverter.class.getName());
        when(mappedBy.field()).thenReturn(MappedBy.DEFAULT_FIELD);
        when(reflectionHelper.newInstance(NoConversionTypeConverter.class.getName()))
                .thenThrow(new IllegalAccessException());

        exception.expect(JTransfoException.class);
        exception.expectMessage(
                "Declared TypeConverter class org.jtransfo.NoConversionTypeConverter cannot be accessed.");
        converterHelper.getDeclaredTypeConverter(mappedBy);
    }

    @Test
    public void testGetDeclaredTypeConverterCce() throws Exception {
        MappedBy mappedBy = mock(MappedBy.class);
        when(mappedBy.typeConverterClass()).thenReturn(MappedBy.DefaultTypeConverter.class);
        when(mappedBy.typeConverter()).thenReturn(NoConversionTypeConverter.class.getName());
        when(mappedBy.field()).thenReturn(MappedBy.DEFAULT_FIELD);
        when(reflectionHelper.newInstance(NoConversionTypeConverter.class.getName()))
                .thenThrow(new ClassCastException());

        exception.expect(JTransfoException.class);
        exception.expectMessage("Declared TypeConverter class org.jtransfo.NoConversionTypeConverter "
                + "cannot be cast to a TypeConverter.");
        converterHelper.getDeclaredTypeConverter(mappedBy);
    }

    @Test
    public void testGetDefaultTypeConverterEmptyList() throws Exception {

        TypeConverter typeConverter = converterHelper.getDefaultTypeConverter(Object.class, Date.class);

        assertThat(typeConverter).isInstanceOf(NoConversionTypeConverter.class);
    }

    @Test
    public void testGetDefaultTypeConverterMatchingConverter() throws Exception {
        TypeConverter typeConverter = mock(TypeConverter.class);
        when(typeConverter.canConvert(any(Class.class), any(Class.class))).thenReturn(true);
        ReflectionTestUtils.setField(converterHelper, "typeConvertersInOrder",
                Collections.singletonList(typeConverter));

        TypeConverter result = converterHelper.getDefaultTypeConverter(Object.class, Date.class);

        assertThat(result).isEqualTo(typeConverter);
    }

    @Test
    public void testGetDefaultTypeConverterNoMatchingConverter() throws Exception {
        List<TypeConverter> tcs = new ArrayList<TypeConverter>();
        tcs.add(new DefaultTypeConverter());
        tcs.add(new DefaultTypeConverter());
        ReflectionTestUtils.setField(converterHelper, "typeConvertersInOrder", tcs);

        TypeConverter typeConverter = converterHelper.getDefaultTypeConverter(Object.class, Date.class);

        assertThat(typeConverter).isInstanceOf(NoConversionTypeConverter.class);
    }

    @Test
    public void testGetToConverter() throws Exception {
        ReflectionTestUtils.setField(converterHelper, "reflectionHelper", new ReflectionHelper()); // echte gebruiken

        ToConverter res = converterHelper.getToConverter(SimpleExtendedTo.class, SimpleExtendedDomain.class);

        assertThat(res).isNotNull();
        assertThat(res.getToTo()).hasSize(4);
        assertThat(res.getToTo().get(0)).isInstanceOf(ToToConverter.class);
        assertThat(res.getToDomain()).hasSize(3);
        assertThat(res.getToDomain().get(0)).isInstanceOf(ToDomainConverter.class);
    }

    @Test
    public void testGetToConverter_mapOnly() throws Exception {
        ReflectionTestUtils.setField(converterHelper, "reflectionHelper", new ReflectionHelper()); // echte gebruiken
        ((Map<String, TypeConverter>) ReflectionTestUtils.getField(converterHelper, "typeConverterInstances"))
                .put("always2", new DefaultTypeConverter());

        ToConverter res = converterHelper.getToConverter(TaggedPersonTo.class, PersonDomain.class);

        assertThat(res).isNotNull();
        assertThat(res.getToTo()).hasSize(4);
        assertThat(res.getToTo().get(0)).isInstanceOf(TaggedConverter.class);
        assertThat(res.getToDomain()).hasSize(3);
        assertThat(res.getToDomain().get(0)).isInstanceOf(TaggedConverter.class);
    }

    @Test
    public void testGetToConverterTransitive() throws Exception {
        ReflectionTestUtils.setField(converterHelper, "reflectionHelper", new ReflectionHelper()); // echte gebruiken

        ToConverter res = converterHelper.getToConverter(PersonTransitiveTo.class, PersonDomain.class);

        assertThat(res).isNotNull();
        assertThat(res.getToTo()).hasSize(3);
        assertThat(res.getToDomain()).hasSize(3);
    }

    @Test
    public void testGetToConverterInvalidMapping() throws Exception {
        ReflectionTestUtils.setField(converterHelper, "reflectionHelper", new ReflectionHelper()); // echte gebruiken

        exception.expect(JTransfoException.class);
        exception.expectMessage("Cannot determine mapping for field string in class "
                + "org.jtransfo.object.FaultyExtendedTo. The field zzz in class "
                + "org.jtransfo.object.SimpleExtendedDomain cannot be found.");

        converterHelper.getToConverter(FaultyExtendedTo.class, SimpleExtendedDomain.class);
    }

    @Test
    public void testSetTypeConvertersInOrder() throws Exception {
        List org = (List) ReflectionTestUtils.getField(converterHelper, "typeConvertersInOrder");
        TypeConverter typeConverter = mock(TypeConverter.class);
        assertThat(org.size()).isEqualTo(0); // default is empty

        converterHelper.setTypeConvertersInOrder(Collections.singletonList(typeConverter));
        List res = (List) ReflectionTestUtils.getField(converterHelper, "typeConvertersInOrder");
        assertThat(res.size()).isEqualTo(1);
        assertThat((Object) res).isInstanceOf(LockableList.class);
        assertThat((Boolean) ReflectionTestUtils.getField(res, "readOnly")).isTrue();
    }

    @Test
    public void testSetTypeConvertersInOrderNamed() throws Exception {
        List org = (List) ReflectionTestUtils.getField(converterHelper, "typeConvertersInOrder");
        NamedTypeConverter typeConverter = mock(NamedTypeConverter.class);
        assertThat(org.size()).isEqualTo(0); // default is empty

        converterHelper.setTypeConvertersInOrder((Collection) Collections.singletonList(typeConverter));
        List res = (List) ReflectionTestUtils.getField(converterHelper, "typeConvertersInOrder");
        assertThat(res.size()).isEqualTo(1);
        assertThat((Object) res).isInstanceOf(LockableList.class);
        assertThat((Boolean) ReflectionTestUtils.getField(res, "readOnly")).isTrue();
        verify(typeConverter).getName();
    }

    @Test
    public void testWithPath() throws Exception {
        assertThat(converterHelper.withPath(new String[] { "parts", "to", "add" }))
                .isEqualTo(" (with path parts.to.add) ");
    }

    @Test
    public void testGetDeclaredTypeConverter() throws Exception {
        MapOnly mapOnly = mock(MapOnly.class);
        when(mapOnly.typeConverterClass()).thenReturn(MappedBy.DefaultTypeConverter.class);
        when(mapOnly.typeConverter()).thenReturn(MappedBy.DEFAULT_TYPE_CONVERTER);
        TypeConverter tc = mock(TypeConverter.class);

        TypeConverter res = converterHelper.getDeclaredTypeConverter(mapOnly, tc);

        assertThat(res).isEqualTo(tc);
    }

    @Test
    public void testGetDeclaredTypeConverter_withTypeConverter() throws Exception {
        MapOnly mapOnly = mock(MapOnly.class);
        when(reflectionHelper.newInstance("org.jtransfo.internal.ConverterHelperTest$DefaultTypeConverter"))
                .thenReturn(new DefaultTypeConverter());
        when(mapOnly.typeConverterClass()).thenReturn(DefaultTypeConverter.class);
        when(mapOnly.typeConverter()).thenReturn(MappedBy.DEFAULT_TYPE_CONVERTER);
        TypeConverter tc = mock(TypeConverter.class);

        TypeConverter res = converterHelper.getDeclaredTypeConverter(mapOnly, tc);

        assertThat(res).isInstanceOf(DefaultTypeConverter.class);
    }

    @Test
    public void testGetMapOnlies_both() throws Exception {
        Field field = TaggedPersonTo.class.getDeclaredField("gender"); // has both annotations
        field.setAccessible(true);

        List<MapOnly> res = converterHelper.getMapOnlies(field);

        assertThat(res).hasSize(2); // one MapOnly, one in MapOnlies
    }

    @Test
    public void testGetMapOnlies_mapOnlies() throws Exception {
        Field field = TaggedPersonTo.class.getDeclaredField("name"); // has both annotations
        field.setAccessible(true);

        List<MapOnly> res = converterHelper.getMapOnlies(field);

        assertThat(res).hasSize(2); // no MapOnly, two in MapOnlies
    }

    @Test
    public void testGetMapOnlies_none() throws Exception {
        Field field = TaggedPersonTo.class.getDeclaredField("lastChanged"); // has both annotations
        field.setAccessible(true);

        List<MapOnly> res = converterHelper.getMapOnlies(field);

        assertThat(res).isNull(); // neither -> null
    }

    @Test
    public void testGetDeclaredTypeConverter_null() throws Exception {
        TypeConverter tc = mock(TypeConverter.class);

        TypeConverter res = converterHelper.getDeclaredTypeConverter(null, tc);

        assertThat(res).isEqualTo(tc);
    }

    private class DefaultTypeConverter implements TypeConverter<Object, Object> {

        @Override
        public boolean canConvert(Class<?> realToType, Class<?> realDomainType) {
            return false;
        }

        @Override
        public Object convert(Object object, SyntheticField domainField, Object domainObject, String... tags)
                throws JTransfoException {
            return null;
        }

        @Override
        public Object reverse(Object object, SyntheticField toField, Object toObject, String... tags)
                throws JTransfoException {
            return null;
        }
    }

    private interface NamedTypeConverter extends TypeConverter, Named {
    }
}