package com.constellio.model.utils;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.fail;
import static org.mockito.BDDMockito.willThrow;
import static org.mockito.Mockito.when;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import org.jdom2.Attribute;
import org.jdom2.Element;
import org.joda.time.LocalDate;
import org.joda.time.LocalDateTime;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Mockito;
import com.constellio.model.entities.schemas.Metadata;
import com.constellio.model.utils.ParametrizedInstanceUtilsRuntimeException.CannotInstanciate;
import com.constellio.model.utils.ParametrizedInstanceUtilsRuntimeException.UnsupportedArgument;
import com.constellio.model.utils.ParametrizedInstanceUtilsTestResources.CorrectParametrizedClass;
import com.constellio.model.utils.ParametrizedInstanceUtilsTestResources.PrivateConstructorClass;
import com.constellio.model.utils.ParametrizedInstanceUtilsTestResources.UnsupportedArgumentClass;
import com.constellio.model.utils.ParametrizedInstanceUtilsTestResources.UnsupportedChildArgumentClass;
public class ParametrizedInstanceUtilsTest {
ParametrizedInstanceUtils utils;
private CorrectParametrizedClass correctParametrizedClass;
private CorrectParametrizedClass nullValueParametrizedClass;
private CorrectParametrizedClass multipleNullValueParametrizedClass;
private Element rootElement;
@Before
public void setUp()
throws Exception {
utils = new ParametrizedInstanceUtils();
rootElement = Mockito.mock(Element.class);
List<String> metadatas = new ArrayList<>();
metadatas.add("metadata");
metadatas.add("metadata");
metadatas.add("metadata");
List<Integer> mapValue = new ArrayList<>();
mapValue.add(1);
mapValue.add(1);
HashMap<String, List<Integer>> values = new HashMap<>();
values.put("entry1", mapValue);
values.put("entry2", null);
values.put("entry3", mapValue);
LocalDateTime aDateTime = new LocalDateTime();
LocalDate aDate = new LocalDate();
double aDouble = 2.0;
correctParametrizedClass = new CorrectParametrizedClass(metadatas, values, false, aDateTime, aDate, aDouble);
nullValueParametrizedClass = new CorrectParametrizedClass(null, values, false, aDateTime, aDate, aDouble);
multipleNullValueParametrizedClass = new CorrectParametrizedClass(null, values, null, aDateTime, aDate, null);
}
@Test
public void givenCorrectParametrizedClassThenSaveAndLoadThenSameClassLoaded() {
Element classElement = utils.toElement(correctParametrizedClass, "parameter");
CorrectParametrizedClass loaded = utils.toObject(classElement, correctParametrizedClass.getClass());
assertThat(loaded.getInstanceParameters()).isEqualTo(correctParametrizedClass.getInstanceParameters());
}
@Test
public void givenNullValueParametrizedClassThenSaveAndLoadThenSameClassLoaded() {
Element classElement = utils.toElement(nullValueParametrizedClass, "parameter");
CorrectParametrizedClass loaded = utils.toObject(classElement, nullValueParametrizedClass.getClass());
assertThat(loaded.getInstanceParameters()).isEqualTo(nullValueParametrizedClass.getInstanceParameters());
}
@Test
public void givenDoubleNullValueParametrizedClassThenSaveAndLoadThenSameClassLoaded() {
Element classElement = utils.toElement(multipleNullValueParametrizedClass, "parameter");
CorrectParametrizedClass loaded = utils.toObject(classElement, multipleNullValueParametrizedClass.getClass());
assertThat(loaded.getInstanceParameters()).isEqualTo(multipleNullValueParametrizedClass.getInstanceParameters());
}
@Test(expected = UnsupportedArgument.class)
public void givenUnsupportedArgumentThenUnsupportedArgumentThrown() {
Metadata metadata = Mockito.mock(Metadata.class);
Element classElement = utils.toElement(new UnsupportedArgumentClass(metadata), "parameter");
fail();
}
@Test(expected = UnsupportedArgument.class)
public void givenUnsupportedChildArgumentThenUnsupportedArgumentThrown() {
Metadata metadata = Mockito.mock(Metadata.class);
List<Metadata> metadatas = new ArrayList<>();
metadatas.add(metadata);
Element classElement = utils.toElement(new UnsupportedChildArgumentClass(metadatas), "parameter");
fail();
}
@Test(expected = CannotInstanciate.class)
public void givenReflectionExceptionInParameterThenCannotInstanciateThrown() {
List<Class<?>> parameterClasses = Mockito.mock(List.class);
List<Object> parameters = Mockito.mock(List.class);
when(rootElement.getAttribute("name")).thenReturn(new Attribute("name",
"com.constellio.model.utils.ParametrizedInstanceUtilsTestResources.CorrectParametrizedClass"));
ParametrizedInstanceUtils parametrizedUtils = Mockito.mock(ParametrizedInstanceUtils.class);
willThrow(InstantiationException.class).given(parametrizedUtils).getConstructorParameter(rootElement, parameters,
parameterClasses);
when(parametrizedUtils.toObject(rootElement, correctParametrizedClass.getClass())).thenCallRealMethod();
parametrizedUtils.toObject(rootElement, correctParametrizedClass.getClass());
fail();
}
@Test(expected = CannotInstanciate.class)
public void givenReflectionExceptionInSubParameterThenCannotInstanciateThrown()
throws InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {
when(rootElement.getAttribute("type")).thenReturn(new Attribute("type",
"java.lang.String"));
ParametrizedInstanceUtils parametrizedUtils = Mockito.mock(ParametrizedInstanceUtils.class);
willThrow(InstantiationException.class).given(parametrizedUtils).getObject(rootElement, String.class);
when(parametrizedUtils.toObject(rootElement)).thenCallRealMethod();
parametrizedUtils.toObject(rootElement);
fail();
}
@Test(expected = CannotInstanciate.class)
public void givenPrivateConstructorClassThenNoSuchConstructorThrown() {
Element privateConstructorClass = Mockito.mock(Element.class);
when(privateConstructorClass.getAttribute("name")).thenReturn(new Attribute("name",
"com.constellio.model.utils.ParametrizedInstanceUtilsTestResources.PrivateConstructorClass"));
utils.toObject(privateConstructorClass, PrivateConstructorClass.class);
fail();
}
@Test(expected = CannotInstanciate.class)
public void givenIncorrectClassThenSaveAndLoadThenNoSuchClassThrown() {
when(rootElement.getAttribute("name")).thenReturn(new Attribute("name", "com.constellio.model.utils.Nonexistent"));
utils.toObject(rootElement, CorrectParametrizedClass.class);
fail();
}
}