From 2fe5c35460f88b39576c546b28248f3cd58b7dd3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20Jo=C5=84ski?= Date: Sat, 16 Dec 2017 21:04:53 +0100 Subject: [PATCH] 217. Classes can be instantiated by user defined instantiators. --- .../api/AbstractObjectInstantiator.java | 40 +++++++ .../api/assertion/AbstractAssertion.java | 108 +++++++++++++----- .../AbstractInternalInstantiator.java | 17 +++ .../AbstractMultiConstructorInstantiator.java | 87 ++++---------- .../AbstractObjectInstantiator.java | 20 ---- .../instantiator/ArrayInstantiator.java | 10 +- .../BestConstructorInstantiator.java | 15 +-- .../instantiator/CollectionInstantiator.java | 10 +- .../DefaultConstructorInstantiator.java | 10 +- .../instantiator/EnumInstantiator.java | 10 +- .../internal/instantiator/Instantiable.java | 63 +++++----- .../instantiator/JavaTypeInstantiator.java | 10 +- .../instantiator/ObjectGenerator.java | 11 +- .../instantiator/ProxyInstantiator.java | 25 ++-- .../instantiator/SupplierInstantiator.java | 25 ++++ .../UserDefinedConstructorInstantiator.java | 60 +++++----- .../internal/tester/AbstractTester.java | 28 ++--- .../internal/tester/ConstructorTester.java | 38 +----- .../java/helpers/MultiValuedMapMatcher.java | 35 ------ .../api/assertion/AbstractAssertionTest.java | 57 ++++----- ...tractMultiConstructorInstantiatorTest.java | 45 +------- .../instantiator/ArrayInstantiatorTest.java | 4 +- .../BestConstructorInstantiatorTest.java | 36 +++--- .../CollectionInstantiatorTest.java | 7 +- .../DefaultConstructorInstantiatorTest.java | 7 +- .../instantiator/EnumInstantiatorTest.java | 7 +- .../instantiator/InstantiableTest.java | 31 +++-- .../JavaTypeInstantiatorTest.java | 7 +- .../instantiator/ObjectGeneratorFastTest.java | 28 ++--- .../instantiator/ObjectGeneratorTest.java | 28 ++--- .../instantiator/ProxyInstantiatorTest.java | 11 +- ...serDefinedConstructorInstantiatorTest.java | 27 +---- .../internal/tester/AbstractTesterTest.java | 10 +- .../tester/ConstructorTesterTest.java | 58 +--------- 34 files changed, 401 insertions(+), 584 deletions(-) create mode 100644 src/main/java/pl/pojo/tester/api/AbstractObjectInstantiator.java create mode 100644 src/main/java/pl/pojo/tester/internal/instantiator/AbstractInternalInstantiator.java delete mode 100644 src/main/java/pl/pojo/tester/internal/instantiator/AbstractObjectInstantiator.java create mode 100644 src/main/java/pl/pojo/tester/internal/instantiator/SupplierInstantiator.java delete mode 100644 src/test/java/helpers/MultiValuedMapMatcher.java diff --git a/src/main/java/pl/pojo/tester/api/AbstractObjectInstantiator.java b/src/main/java/pl/pojo/tester/api/AbstractObjectInstantiator.java new file mode 100644 index 00000000..d8cb7c0d --- /dev/null +++ b/src/main/java/pl/pojo/tester/api/AbstractObjectInstantiator.java @@ -0,0 +1,40 @@ +package pl.pojo.tester.api; + +/** + * This is a base class for all instantiators. + * + * @author Piotr JoĊ„ski + * @since 0.8.0 + */ +public abstract class AbstractObjectInstantiator { + + protected final Class clazz; + + /** + * Creates new instantiator for defined class. + * + * @param clazz class that will be instantiated + */ + public AbstractObjectInstantiator(final Class clazz) { + this.clazz = clazz; + } + + /** + * Produces new instances of given class. + * + * @return new object that class is defined in constructor. + */ + public abstract Object instantiate(); + + /** + * @return class defined in constructor. + */ + public Class getClazz() { + return clazz; + } + + @Override + public String toString() { + return "AbstractObjectInstantiator{clazz=" + clazz + '}'; + } +} diff --git a/src/main/java/pl/pojo/tester/api/assertion/AbstractAssertion.java b/src/main/java/pl/pojo/tester/api/assertion/AbstractAssertion.java index de87273d..630eee3c 100644 --- a/src/main/java/pl/pojo/tester/api/assertion/AbstractAssertion.java +++ b/src/main/java/pl/pojo/tester/api/assertion/AbstractAssertion.java @@ -1,20 +1,24 @@ package pl.pojo.tester.api.assertion; -import org.apache.commons.collections4.MultiValuedMap; -import org.apache.commons.collections4.multimap.ArrayListValuedHashMap; import org.slf4j.Logger; +import pl.pojo.tester.api.AbstractObjectInstantiator; import pl.pojo.tester.api.ClassAndFieldPredicatePair; import pl.pojo.tester.api.ConstructorParameters; import pl.pojo.tester.internal.field.AbstractFieldValueChanger; +import pl.pojo.tester.internal.instantiator.SupplierInstantiator; +import pl.pojo.tester.internal.instantiator.UserDefinedConstructorInstantiator; +import pl.pojo.tester.internal.tester.AbstractTester; +import pl.pojo.tester.internal.utils.ClassLoader; import pl.pojo.tester.internal.utils.Permutator; import pl.pojo.tester.internal.utils.SublistFieldPermutator; import pl.pojo.tester.internal.utils.ThoroughFieldPermutator; -import pl.pojo.tester.internal.tester.AbstractTester; -import pl.pojo.tester.internal.utils.ClassLoader; import java.util.Arrays; import java.util.HashSet; +import java.util.LinkedList; +import java.util.List; import java.util.Set; +import java.util.function.Supplier; import java.util.stream.Collectors; import static pl.pojo.tester.internal.preconditions.ParameterPreconditions.checkNotBlank; @@ -40,7 +44,7 @@ public abstract class AbstractAssertion { .forEach(DEFAULT_TESTERS::add); } - private final MultiValuedMap, ConstructorParameters> constructorParameters = new ArrayListValuedHashMap<>(); + private final List instantiators = new LinkedList<>(); Set testers = new HashSet<>(); private AbstractFieldValueChanger abstractFieldValueChanger; private Permutator permutator = new ThoroughFieldPermutator(); @@ -109,26 +113,6 @@ public AbstractAssertion testing(final Method method) { return this; } - /** - * Performs specified tests on classes using declared field value changer. - * - * @see Method - * @see AbstractFieldValueChanger - */ - public void areWellImplemented() { - if (testers.isEmpty()) { - testers = DEFAULT_TESTERS; - } - if (abstractFieldValueChanger != null) { - testers.forEach(tester -> tester.setFieldValuesChanger(abstractFieldValueChanger)); - } - - testers.forEach(tester -> tester.setPermutator(permutator)); - testers.forEach(tester -> tester.setUserDefinedConstructors(constructorParameters)); - - runAssertions(); - } - /** * Indicates, that class should be constructed using given constructor parameters. Constructor will be selected * based on constructor parameter's types. @@ -164,8 +148,8 @@ public AbstractAssertion create(final String qualifiedClassName, checkNotNull("constructorParameters", constructorParameters); final Class clazz = ClassLoader.loadClass(qualifiedClassName); - this.constructorParameters.put(clazz, constructorParameters); - return this; + + return create(clazz, constructorParameters); } /** @@ -188,7 +172,6 @@ public AbstractAssertion create(final Class clazz, return create(clazz, constructorParameter); } - /** * Indicates, that class should be constructed using given constructor parameters. Constructor will be selected * based on constructor parameter's types. @@ -202,10 +185,76 @@ public AbstractAssertion create(final Class clazz, final ConstructorParameter checkNotNull("clazz", clazz); checkNotNull("constructorParameters", constructorParameters); - this.constructorParameters.put(clazz, constructorParameters); + final UserDefinedConstructorInstantiator instantiator = new UserDefinedConstructorInstantiator(clazz, + constructorParameters); + return create(clazz, instantiator); + } + + /** + * Indicates, that class should be constructed using given instantiator. + * + * @param instantiator instantiator which will create instance of given class + * @return itself + * @see ConstructorParameters + */ + public AbstractAssertion create(final AbstractObjectInstantiator instantiator) { + checkNotNull("clazz", instantiator.getClazz()); + checkNotNull("instantiator", instantiator); + + return create(instantiator.getClazz(), instantiator::instantiate); + } + + /** + * Indicates, that class should be constructed using given instantiator. + * + * @param clazz class to instantiate + * @param instantiator instantiator which will create instance of given class + * @return itself + * @see ConstructorParameters + */ + public AbstractAssertion create(final Class clazz, final AbstractObjectInstantiator instantiator) { + checkNotNull("clazz", clazz); + checkNotNull("instantiator", instantiator); + + return create(clazz, instantiator::instantiate); + } + + /** + * Indicates, that class should be constructed using given supplier. + * + * @param clazz class to instantiate + * @param supplier supplier that will create given class + * @return itself + * @see ConstructorParameters + */ + public AbstractAssertion create(final Class clazz, final Supplier supplier) { + checkNotNull("clazz", clazz); + checkNotNull("supplier", supplier); + + this.instantiators.add(new SupplierInstantiator(clazz, supplier)); return this; } + /** + * Performs specified tests on classes using declared field value changer. + * + * @see Method + * @see AbstractFieldValueChanger + */ + public void areWellImplemented() { + if (testers.isEmpty()) { + testers = DEFAULT_TESTERS; + } + if (abstractFieldValueChanger != null) { + testers.forEach(tester -> tester.setFieldValuesChanger(abstractFieldValueChanger)); + } + + testers.forEach(tester -> tester.setPermutator(permutator)); + testers.forEach(tester -> tester.setUserDefinedInstantiators(instantiators)); + + runAssertions(); + } + protected abstract void runAssertions(); protected void logTestersAndClasses(final Logger logger, @@ -218,6 +267,7 @@ protected void logTestersAndClasses(final Logger logger, logger.debug("Running {} testers on {} classes", testers.size(), classAndFieldPredicatePairs.length); logger.debug("Testers: {}", testers); logger.debug("Classes: {}", classes); + logger.debug("Predefined instantiators: {}", instantiators); } } } diff --git a/src/main/java/pl/pojo/tester/internal/instantiator/AbstractInternalInstantiator.java b/src/main/java/pl/pojo/tester/internal/instantiator/AbstractInternalInstantiator.java new file mode 100644 index 00000000..d5be0fc5 --- /dev/null +++ b/src/main/java/pl/pojo/tester/internal/instantiator/AbstractInternalInstantiator.java @@ -0,0 +1,17 @@ +package pl.pojo.tester.internal.instantiator; + +import pl.pojo.tester.api.AbstractObjectInstantiator; + +abstract class AbstractInternalInstantiator extends AbstractObjectInstantiator { + + AbstractInternalInstantiator(final Class clazz) { + super(clazz); + } + + abstract boolean canInstantiate(); + + @Override + public String toString() { + return "AbstractInternalInstantiator{clazz=" + clazz + '}'; + } +} diff --git a/src/main/java/pl/pojo/tester/internal/instantiator/AbstractMultiConstructorInstantiator.java b/src/main/java/pl/pojo/tester/internal/instantiator/AbstractMultiConstructorInstantiator.java index 220e11be..8c37ee29 100644 --- a/src/main/java/pl/pojo/tester/internal/instantiator/AbstractMultiConstructorInstantiator.java +++ b/src/main/java/pl/pojo/tester/internal/instantiator/AbstractMultiConstructorInstantiator.java @@ -1,66 +1,35 @@ package pl.pojo.tester.internal.instantiator; -import org.apache.commons.collections4.MultiValuedMap; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import pl.pojo.tester.api.ConstructorParameters; -import pl.pojo.tester.internal.utils.CollectionUtils; +import pl.pojo.tester.api.AbstractObjectInstantiator; import java.lang.reflect.Constructor; -import java.lang.reflect.Modifier; import java.util.Arrays; -import java.util.Collection; +import java.util.List; import java.util.Objects; -import java.util.stream.Stream; +import java.util.Optional; -abstract class AbstractMultiConstructorInstantiator extends AbstractObjectInstantiator { +abstract class AbstractMultiConstructorInstantiator extends AbstractInternalInstantiator { private static final Logger LOGGER = LoggerFactory.getLogger(AbstractMultiConstructorInstantiator.class); + private final List instantiators; - AbstractMultiConstructorInstantiator(final Class clazz, - final MultiValuedMap, ConstructorParameters> constructorParameters) { - super(clazz, constructorParameters); + AbstractMultiConstructorInstantiator(final Class clazz, final List instantiators) { + super(clazz); + this.instantiators = instantiators; } - protected Object instantiateUsingUserParameters() { - final Collection userConstructorParameters = constructorParameters.get(clazz); - if (userDefinedOwnParametersForThisClass(userConstructorParameters)) { - final Object result = tryToInstantiateUsing(userConstructorParameters); - if (result != null) { - return result; - } - LOGGER.warn("Could not instantiate class {} with user defined parameters. " - + "Trying create instance finding best constructor", clazz); - } - return null; - } - - private boolean userDefinedOwnParametersForThisClass(final Collection userConstructorParameters) { - return CollectionUtils.isNotEmpty(userConstructorParameters); - } + protected Object createFindingBestConstructor() { + final Optional instantiator = findFirstMatchingInPredefined(); - private Object tryToInstantiateUsing(final Collection userConstructorParameters) { - for (final ConstructorParameters param : userConstructorParameters) { - Class[] parameterTypes = param.getParametersTypes(); - try { - Object[] parameters = param.getParameters(); - if (isInnerClass()) { - parameterTypes = putEnclosingClassAsFirstParameterType(clazz.getEnclosingClass(), parameterTypes); - final Object enclosingClassInstance = instantiateEnclosingClass(); - parameters = putEnclosingClassInstanceAsFirstParameter(enclosingClassInstance, parameters); - } - return createObjectFromArgsConstructor(parameterTypes, parameters); - } catch (final ObjectInstantiationException e) { - LOGGER.debug("ObjectInstantiationException:", e); - // ignore, try all user defined constructor parameters and types - } + if (instantiator.isPresent()) { + return instantiator.get() + .instantiate(); } - return null; - } - protected Object createFindingBestConstructor() { final Constructor[] constructors = clazz.getDeclaredConstructors(); return Arrays.stream(constructors) .map(this::createObjectFromConstructor) @@ -69,34 +38,18 @@ protected Object createFindingBestConstructor() { .orElseThrow(this::createObjectInstantiationException); } + private Optional findFirstMatchingInPredefined() { + return instantiators.stream() + .filter(eachInstantiator -> clazz.equals(eachInstantiator.getClazz())) + .findFirst(); + } + protected abstract Object createObjectFromArgsConstructor(final Class[] parameterTypes, Object[] parameters); protected abstract Object createObjectFromNoArgsConstructor(final Constructor constructor); protected abstract ObjectInstantiationException createObjectInstantiationException(); - private Object instantiateEnclosingClass() { - final Class enclosingClass = clazz.getEnclosingClass(); - return Instantiable.forClass(enclosingClass, constructorParameters) - .instantiate(); - } - - private Class[] putEnclosingClassAsFirstParameterType(final Class enclosingClass, - final Class[] constructorParametersTypes) { - return Stream.concat(Stream.of(enclosingClass), Arrays.stream(constructorParametersTypes)) - .toArray(Class[]::new); - } - - private boolean isInnerClass() { - return clazz.getEnclosingClass() != null && !Modifier.isStatic(clazz.getModifiers()); - } - - private Object[] putEnclosingClassInstanceAsFirstParameter(final Object enclosingClassInstance, - final Object[] arguments) { - return Stream.concat(Stream.of(enclosingClassInstance), Arrays.stream(arguments)) - .toArray(Object[]::new); - } - private Object createObjectFromConstructor(final Constructor constructor) { makeAccessible(constructor); if (constructor.getParameterCount() == 0) { @@ -104,7 +57,7 @@ private Object createObjectFromConstructor(final Constructor constructor) { } else { try { final Object[] parameters = Instantiable.instantiateClasses(constructor.getParameterTypes(), - constructorParameters); + instantiators); return createObjectFromArgsConstructor(constructor.getParameterTypes(), parameters); } catch (final Exception e) { LOGGER.debug("Exception:", e); diff --git a/src/main/java/pl/pojo/tester/internal/instantiator/AbstractObjectInstantiator.java b/src/main/java/pl/pojo/tester/internal/instantiator/AbstractObjectInstantiator.java deleted file mode 100644 index 18964897..00000000 --- a/src/main/java/pl/pojo/tester/internal/instantiator/AbstractObjectInstantiator.java +++ /dev/null @@ -1,20 +0,0 @@ -package pl.pojo.tester.internal.instantiator; - -import org.apache.commons.collections4.MultiValuedMap; -import pl.pojo.tester.api.ConstructorParameters; - -abstract class AbstractObjectInstantiator { - - protected final Class clazz; - protected final MultiValuedMap, ConstructorParameters> constructorParameters; - - AbstractObjectInstantiator(final Class clazz, - final MultiValuedMap, ConstructorParameters> constructorParameters) { - this.clazz = clazz; - this.constructorParameters = constructorParameters; - } - - public abstract Object instantiate(); - - public abstract boolean canInstantiate(); -} diff --git a/src/main/java/pl/pojo/tester/internal/instantiator/ArrayInstantiator.java b/src/main/java/pl/pojo/tester/internal/instantiator/ArrayInstantiator.java index 9465e99d..d5e36baa 100644 --- a/src/main/java/pl/pojo/tester/internal/instantiator/ArrayInstantiator.java +++ b/src/main/java/pl/pojo/tester/internal/instantiator/ArrayInstantiator.java @@ -1,17 +1,13 @@ package pl.pojo.tester.internal.instantiator; -import org.apache.commons.collections4.MultiValuedMap; -import pl.pojo.tester.api.ConstructorParameters; - import java.lang.reflect.Array; -class ArrayInstantiator extends AbstractObjectInstantiator { +class ArrayInstantiator extends AbstractInternalInstantiator { private static final int DEFAULT_ARRAY_LENGTH = 0; - ArrayInstantiator(final Class clazz, - final MultiValuedMap, ConstructorParameters> constructorParameters) { - super(clazz, constructorParameters); + ArrayInstantiator(final Class clazz) { + super(clazz); } @Override diff --git a/src/main/java/pl/pojo/tester/internal/instantiator/BestConstructorInstantiator.java b/src/main/java/pl/pojo/tester/internal/instantiator/BestConstructorInstantiator.java index 142d63e1..9d6e9c82 100644 --- a/src/main/java/pl/pojo/tester/internal/instantiator/BestConstructorInstantiator.java +++ b/src/main/java/pl/pojo/tester/internal/instantiator/BestConstructorInstantiator.java @@ -1,30 +1,25 @@ package pl.pojo.tester.internal.instantiator; -import org.apache.commons.collections4.MultiValuedMap; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import pl.pojo.tester.api.ConstructorParameters; +import pl.pojo.tester.api.AbstractObjectInstantiator; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; +import java.util.List; class BestConstructorInstantiator extends AbstractMultiConstructorInstantiator { private static final Logger LOGGER = LoggerFactory.getLogger(BestConstructorInstantiator.class); - BestConstructorInstantiator(final Class clazz, - final MultiValuedMap, ConstructorParameters> constructorParameters) { - super(clazz, constructorParameters); + BestConstructorInstantiator(final Class clazz, final List instantiators) { + super(clazz, instantiators); } @Override public Object instantiate() { - Object result = instantiateUsingUserParameters(); - if (result == null) { - result = createFindingBestConstructor(); - } - return result; + return createFindingBestConstructor(); } @Override diff --git a/src/main/java/pl/pojo/tester/internal/instantiator/CollectionInstantiator.java b/src/main/java/pl/pojo/tester/internal/instantiator/CollectionInstantiator.java index d1b2c026..67e3cd36 100644 --- a/src/main/java/pl/pojo/tester/internal/instantiator/CollectionInstantiator.java +++ b/src/main/java/pl/pojo/tester/internal/instantiator/CollectionInstantiator.java @@ -1,9 +1,6 @@ package pl.pojo.tester.internal.instantiator; -import org.apache.commons.collections4.MultiValuedMap; -import pl.pojo.tester.api.ConstructorParameters; - import java.util.ArrayList; import java.util.Collection; import java.util.Deque; @@ -28,7 +25,7 @@ import java.util.Vector; import java.util.stream.Stream; -class CollectionInstantiator extends AbstractObjectInstantiator { +class CollectionInstantiator extends AbstractInternalInstantiator { private static final Map, Object> PREPARED_OBJECTS = new LinkedHashMap<>(); static { @@ -58,9 +55,8 @@ class CollectionInstantiator extends AbstractObjectInstantiator { PREPARED_OBJECTS.put(Iterable.class, new ArrayList<>()); } - CollectionInstantiator(final Class clazz, - final MultiValuedMap, ConstructorParameters> constructorParameters) { - super(clazz, constructorParameters); + CollectionInstantiator(final Class clazz) { + super(clazz); } @Override diff --git a/src/main/java/pl/pojo/tester/internal/instantiator/DefaultConstructorInstantiator.java b/src/main/java/pl/pojo/tester/internal/instantiator/DefaultConstructorInstantiator.java index 0042159f..067c6861 100644 --- a/src/main/java/pl/pojo/tester/internal/instantiator/DefaultConstructorInstantiator.java +++ b/src/main/java/pl/pojo/tester/internal/instantiator/DefaultConstructorInstantiator.java @@ -1,19 +1,15 @@ package pl.pojo.tester.internal.instantiator; -import org.apache.commons.collections4.MultiValuedMap; -import pl.pojo.tester.api.ConstructorParameters; - import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Modifier; import java.util.Arrays; -class DefaultConstructorInstantiator extends AbstractObjectInstantiator { +class DefaultConstructorInstantiator extends AbstractInternalInstantiator { - DefaultConstructorInstantiator(final Class clazz, - final MultiValuedMap, ConstructorParameters> constructorParameters) { - super(clazz, constructorParameters); + DefaultConstructorInstantiator(final Class clazz) { + super(clazz); } @Override diff --git a/src/main/java/pl/pojo/tester/internal/instantiator/EnumInstantiator.java b/src/main/java/pl/pojo/tester/internal/instantiator/EnumInstantiator.java index f17563b2..3625e22e 100644 --- a/src/main/java/pl/pojo/tester/internal/instantiator/EnumInstantiator.java +++ b/src/main/java/pl/pojo/tester/internal/instantiator/EnumInstantiator.java @@ -1,16 +1,12 @@ package pl.pojo.tester.internal.instantiator; -import org.apache.commons.collections4.MultiValuedMap; -import pl.pojo.tester.api.ConstructorParameters; - import java.util.Random; -class EnumInstantiator extends AbstractObjectInstantiator { +class EnumInstantiator extends AbstractInternalInstantiator { - EnumInstantiator(final Class clazz, - final MultiValuedMap, ConstructorParameters> constructorParameters) { - super(clazz, constructorParameters); + EnumInstantiator(final Class clazz) { + super(clazz); } @Override diff --git a/src/main/java/pl/pojo/tester/internal/instantiator/Instantiable.java b/src/main/java/pl/pojo/tester/internal/instantiator/Instantiable.java index 8049da92..a5026eba 100644 --- a/src/main/java/pl/pojo/tester/internal/instantiator/Instantiable.java +++ b/src/main/java/pl/pojo/tester/internal/instantiator/Instantiable.java @@ -1,14 +1,14 @@ package pl.pojo.tester.internal.instantiator; -import org.apache.commons.collections4.MultiValuedMap; -import pl.pojo.tester.api.ConstructorParameters; +import pl.pojo.tester.api.AbstractObjectInstantiator; -import java.lang.reflect.Constructor; import java.util.ArrayList; import java.util.Arrays; import java.util.LinkedList; import java.util.List; +import java.util.Optional; +import java.util.function.Supplier; public final class Instantiable { @@ -16,7 +16,6 @@ public final class Instantiable { static { INSTANTIATORS = new LinkedList<>(); - INSTANTIATORS.add(UserDefinedConstructorInstantiator.class); INSTANTIATORS.add(JavaTypeInstantiator.class); INSTANTIATORS.add(CollectionInstantiator.class); INSTANTIATORS.add(DefaultConstructorInstantiator.class); @@ -30,38 +29,46 @@ private Instantiable() { } static Object[] instantiateClasses(final Class[] classes, - final MultiValuedMap, ConstructorParameters> constructorParameters) { + final List predefinedInstantiators) { return Arrays.stream(classes) - .map(clazz -> Instantiable.forClass(clazz, constructorParameters)) + .map(clazz -> Instantiable.forClass(clazz, predefinedInstantiators)) .map(AbstractObjectInstantiator::instantiate) .toArray(); } static AbstractObjectInstantiator forClass(final Class clazz, - final MultiValuedMap, ConstructorParameters> constructorParameters) { - return instantiateInstantiators(clazz, constructorParameters).stream() - .filter(AbstractObjectInstantiator::canInstantiate) - .findAny() - .get(); + final List predefinedInstantiators) { + return findPredefinedInstantiator(clazz, predefinedInstantiators) + .orElseGet(findFirstMatchingInstantiator(clazz, predefinedInstantiators)); } - private static List instantiateInstantiators(final Class clazz, - final MultiValuedMap, ConstructorParameters> constructorParameters) { - final List instantiators = new ArrayList<>(); - try { - for (final Class instantiator : INSTANTIATORS) { - final Constructor constructor = - instantiator.getDeclaredConstructor(Class.class, MultiValuedMap.class); - constructor.setAccessible(true); - final AbstractObjectInstantiator abstractObjectInstantiator = constructor.newInstance(clazz, - constructorParameters); - instantiators.add(abstractObjectInstantiator); - } - } catch (final Exception e) { - throw new RuntimeException("Cannot load instantiators form pl.pojo.tester.internal.instantiator package.", - e); - } - return instantiators; + private static Supplier findFirstMatchingInstantiator(final Class clazz, + final List predefinedInstantiators) { + return () -> instantiateInstantiators(clazz, predefinedInstantiators).stream() + .filter(AbstractInternalInstantiator::canInstantiate) + .findFirst() + .get(); + } + + private static Optional findPredefinedInstantiator(final Class clazz, + final List predefinedInstantiators) { + return predefinedInstantiators.stream() + .filter(instantiator -> clazz.equals(instantiator.getClazz())) + .findFirst(); } + private static List instantiateInstantiators(final Class clazz, + final List predefinedInstantiators) { + final List instantiators = new ArrayList<>(); + + instantiators.add(new JavaTypeInstantiator(clazz)); + instantiators.add(new CollectionInstantiator(clazz)); + instantiators.add(new DefaultConstructorInstantiator(clazz)); + instantiators.add(new EnumInstantiator(clazz)); + instantiators.add(new ArrayInstantiator(clazz)); + instantiators.add(new ProxyInstantiator(clazz, predefinedInstantiators)); + instantiators.add(new BestConstructorInstantiator(clazz, predefinedInstantiators)); + + return instantiators; + } } diff --git a/src/main/java/pl/pojo/tester/internal/instantiator/JavaTypeInstantiator.java b/src/main/java/pl/pojo/tester/internal/instantiator/JavaTypeInstantiator.java index fa40e318..8cb8bd3c 100644 --- a/src/main/java/pl/pojo/tester/internal/instantiator/JavaTypeInstantiator.java +++ b/src/main/java/pl/pojo/tester/internal/instantiator/JavaTypeInstantiator.java @@ -1,9 +1,6 @@ package pl.pojo.tester.internal.instantiator; -import org.apache.commons.collections4.MultiValuedMap; -import pl.pojo.tester.api.ConstructorParameters; - import java.math.BigDecimal; import java.math.BigInteger; import java.time.Clock; @@ -26,7 +23,7 @@ import java.util.Map; import java.util.UUID; -class JavaTypeInstantiator extends AbstractObjectInstantiator { +class JavaTypeInstantiator extends AbstractInternalInstantiator { private final Map preparedObjects = new HashMap<>(); @@ -76,9 +73,8 @@ class JavaTypeInstantiator extends AbstractObjectInstantiator { preparedObjects.put(ZoneOffset.class.getName(), ZoneOffset.UTC); } - JavaTypeInstantiator(final Class clazz, - final MultiValuedMap, ConstructorParameters> constructorParameters) { - super(clazz, constructorParameters); + JavaTypeInstantiator(final Class clazz) { + super(clazz); } @Override diff --git a/src/main/java/pl/pojo/tester/internal/instantiator/ObjectGenerator.java b/src/main/java/pl/pojo/tester/internal/instantiator/ObjectGenerator.java index d3b1dab2..1e7d40fd 100644 --- a/src/main/java/pl/pojo/tester/internal/instantiator/ObjectGenerator.java +++ b/src/main/java/pl/pojo/tester/internal/instantiator/ObjectGenerator.java @@ -1,11 +1,10 @@ package pl.pojo.tester.internal.instantiator; -import org.apache.commons.collections4.MultiValuedMap; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import pl.pojo.tester.api.AbstractObjectInstantiator; import pl.pojo.tester.api.ClassAndFieldPredicatePair; -import pl.pojo.tester.api.ConstructorParameters; import pl.pojo.tester.internal.field.AbstractFieldValueChanger; import pl.pojo.tester.internal.utils.FieldUtils; import pl.pojo.tester.internal.utils.Permutator; @@ -27,19 +26,19 @@ public class ObjectGenerator { private static final Logger LOGGER = LoggerFactory.getLogger(ObjectGenerator.class); private final AbstractFieldValueChanger abstractFieldValueChanger; - private final MultiValuedMap, ConstructorParameters> constructorParameters; + private final List additionalInstantiators; private final Permutator permutator; public ObjectGenerator(final AbstractFieldValueChanger abstractFieldValueChanger, - final MultiValuedMap, ConstructorParameters> constructorParameters, + final List additionalInstantiators, final Permutator permutator) { this.abstractFieldValueChanger = abstractFieldValueChanger; - this.constructorParameters = constructorParameters; + this.additionalInstantiators = additionalInstantiators; this.permutator = permutator; } public Object createNewInstance(final Class clazz) { - return Instantiable.forClass(clazz, constructorParameters) + return Instantiable.forClass(clazz, additionalInstantiators) .instantiate(); } diff --git a/src/main/java/pl/pojo/tester/internal/instantiator/ProxyInstantiator.java b/src/main/java/pl/pojo/tester/internal/instantiator/ProxyInstantiator.java index bc215e1c..54e72446 100644 --- a/src/main/java/pl/pojo/tester/internal/instantiator/ProxyInstantiator.java +++ b/src/main/java/pl/pojo/tester/internal/instantiator/ProxyInstantiator.java @@ -2,16 +2,16 @@ import javassist.util.proxy.ProxyFactory; -import org.apache.commons.collections4.MultiValuedMap; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import pl.pojo.tester.api.ConstructorParameters; +import pl.pojo.tester.api.AbstractObjectInstantiator; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.lang.reflect.Modifier; import java.lang.reflect.Proxy; +import java.util.List; class ProxyInstantiator extends AbstractMultiConstructorInstantiator { @@ -20,22 +20,21 @@ class ProxyInstantiator extends AbstractMultiConstructorInstantiator { private final ProxyFactory proxyFactory = new ProxyFactory(); - ProxyInstantiator(final Class clazz, - final MultiValuedMap, ConstructorParameters> constructorParameters) { - super(clazz, constructorParameters); + ProxyInstantiator(final Class clazz, final List instantiators) { + super(clazz, instantiators); } @Override public Object instantiate() { - Object result = instantiateUsingUserParameters(); - if (result == null) { - if (clazz.isAnnotation() || clazz.isInterface()) { - result = proxyByJava(); - } else { - proxyFactory.setSuperclass(clazz); - result = createFindingBestConstructor(); - } + final Object result; + + if (clazz.isAnnotation() || clazz.isInterface()) { + result = proxyByJava(); + } else { + proxyFactory.setSuperclass(clazz); + result = createFindingBestConstructor(); } + return result; } diff --git a/src/main/java/pl/pojo/tester/internal/instantiator/SupplierInstantiator.java b/src/main/java/pl/pojo/tester/internal/instantiator/SupplierInstantiator.java new file mode 100644 index 00000000..944c86f2 --- /dev/null +++ b/src/main/java/pl/pojo/tester/internal/instantiator/SupplierInstantiator.java @@ -0,0 +1,25 @@ +package pl.pojo.tester.internal.instantiator; + +import pl.pojo.tester.api.AbstractObjectInstantiator; + +import java.util.function.Supplier; + +public class SupplierInstantiator extends AbstractObjectInstantiator { + + private final Supplier supplier; + + public SupplierInstantiator(final Class clazz, final Supplier supplier) { + super(clazz); + this.supplier = supplier; + } + + @Override + public Object instantiate() { + return supplier.get(); + } + + @Override + public String toString() { + return "SupplierInstantiator{supplier=" + supplier + ", clazz=" + clazz + '}'; + } +} diff --git a/src/main/java/pl/pojo/tester/internal/instantiator/UserDefinedConstructorInstantiator.java b/src/main/java/pl/pojo/tester/internal/instantiator/UserDefinedConstructorInstantiator.java index 00657d72..9b36a593 100644 --- a/src/main/java/pl/pojo/tester/internal/instantiator/UserDefinedConstructorInstantiator.java +++ b/src/main/java/pl/pojo/tester/internal/instantiator/UserDefinedConstructorInstantiator.java @@ -1,55 +1,35 @@ package pl.pojo.tester.internal.instantiator; -import org.apache.commons.collections4.MultiValuedMap; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import pl.pojo.tester.api.AbstractObjectInstantiator; import pl.pojo.tester.api.ConstructorParameters; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Modifier; import java.util.Arrays; -import java.util.Objects; +import java.util.LinkedList; +import java.util.Optional; import java.util.stream.Stream; -class UserDefinedConstructorInstantiator extends AbstractObjectInstantiator { +public class UserDefinedConstructorInstantiator extends AbstractObjectInstantiator { private static final Logger LOGGER = LoggerFactory.getLogger(BestConstructorInstantiator.class); + private final ConstructorParameters constructorParameters; - UserDefinedConstructorInstantiator(final Class clazz, - final MultiValuedMap, ConstructorParameters> constructorParameters) { - super(clazz, constructorParameters); + public UserDefinedConstructorInstantiator(final Class clazz, final ConstructorParameters constructorParameters) { + super(clazz); + this.constructorParameters = constructorParameters; } @Override public Object instantiate() { - return constructorParameters.get(clazz) - .stream() - .map(this::createObjectUsingConstructorParameters) - .filter(Objects::nonNull) - .findAny() - .orElseThrow(this::createObjectInstantiationException); + return createObjectUsingConstructorParameters(constructorParameters) + .orElseThrow(this::createObjectInstantiationException); } - @Override - public boolean canInstantiate() { - return userDefinedConstructorParameters() && !qualifiesForProxy(clazz); - } - - private boolean userDefinedConstructorParameters() { - return constructorParameters.containsKey(clazz); - } - - private boolean qualifiesForProxy(final Class clazz) { - return clazz.isInterface() || clazz.isAnnotation() || Modifier.isAbstract(clazz.getModifiers()); - } - - private ObjectInstantiationException createObjectInstantiationException() { - return new ObjectInstantiationException(clazz, - "Could not instantiate object by any user defined constructor types and parameters."); - } - - private Object createObjectUsingConstructorParameters(final ConstructorParameters constructorParameters) { + private Optional createObjectUsingConstructorParameters(final ConstructorParameters constructorParameters) { try { Class[] constructorParametersTypes = constructorParameters.getParametersTypes(); Object[] arguments = constructorParameters.getParameters(); @@ -63,17 +43,25 @@ private Object createObjectUsingConstructorParameters(final ConstructorParameter final Constructor constructor = clazz.getDeclaredConstructor(constructorParametersTypes); constructor.setAccessible(true); - return constructor.newInstance(arguments); + return Optional.of(constructor.newInstance(arguments)); } catch (final NoSuchMethodException | InstantiationException | InvocationTargetException | IllegalAccessException | IllegalArgumentException e) { LOGGER.debug("Exception:", e); - return null; + return Optional.empty(); } } + private ObjectInstantiationException createObjectInstantiationException() { + return new ObjectInstantiationException(clazz, + "Could not instantiate object by any user defined constructor types and parameters."); + } + private Object instantiateEnclosingClass() { final Class enclosingClass = clazz.getEnclosingClass(); - return Instantiable.forClass(enclosingClass, constructorParameters) + // TODO create GH issue and explain why creating enclosing class may fail: + // it will fail if one of enclosing class constructor parameter requires user defined instantiator + // currently there is no workaround for this issue + return Instantiable.forClass(enclosingClass, new LinkedList<>()) .instantiate(); } @@ -93,4 +81,8 @@ private boolean isInnerClass() { return clazz.getEnclosingClass() != null && !Modifier.isStatic(clazz.getModifiers()); } + @Override + public String toString() { + return "UserDefinedConstructorInstantiator{constructorParameters=" + constructorParameters + ", clazz=" + clazz + '}'; + } } diff --git a/src/main/java/pl/pojo/tester/internal/tester/AbstractTester.java b/src/main/java/pl/pojo/tester/internal/tester/AbstractTester.java index 53d2ca94..cbed6bef 100644 --- a/src/main/java/pl/pojo/tester/internal/tester/AbstractTester.java +++ b/src/main/java/pl/pojo/tester/internal/tester/AbstractTester.java @@ -1,11 +1,9 @@ package pl.pojo.tester.internal.tester; -import org.apache.commons.collections4.MultiValuedMap; -import org.apache.commons.collections4.multimap.ArrayListValuedHashMap; import org.apache.commons.lang3.builder.EqualsBuilder; import org.apache.commons.lang3.builder.HashCodeBuilder; +import pl.pojo.tester.api.AbstractObjectInstantiator; import pl.pojo.tester.api.ClassAndFieldPredicatePair; -import pl.pojo.tester.api.ConstructorParameters; import pl.pojo.tester.api.FieldPredicate; import pl.pojo.tester.internal.assertion.TestAssertions; import pl.pojo.tester.internal.field.AbstractFieldValueChanger; @@ -15,6 +13,7 @@ import pl.pojo.tester.internal.utils.ThoroughFieldPermutator; import java.util.Arrays; +import java.util.LinkedList; import java.util.List; import java.util.function.Predicate; @@ -23,7 +22,7 @@ public abstract class AbstractTester { final TestAssertions testAssertions = new TestAssertions(); ObjectGenerator objectGenerator; - private MultiValuedMap, ConstructorParameters> constructorParameters = new ArrayListValuedHashMap<>(); + private List instantiators = new LinkedList<>(); private AbstractFieldValueChanger fieldValuesChanger = DefaultFieldValueChanger.INSTANCE; private Permutator permutator = new ThoroughFieldPermutator(); @@ -32,7 +31,7 @@ public AbstractTester() { } public AbstractTester(final AbstractFieldValueChanger abstractFieldValueChanger) { - objectGenerator = new ObjectGenerator(abstractFieldValueChanger, constructorParameters, permutator); + objectGenerator = new ObjectGenerator(abstractFieldValueChanger, instantiators, permutator); } public void test(final Class clazz) { @@ -46,7 +45,8 @@ public void test(final Class clazz, final Predicate fieldPredicate) { test(classAndFieldPredicatePair); } - public abstract void test(final ClassAndFieldPredicatePair baseClassAndFieldPredicatePair, final ClassAndFieldPredicatePair... classAndFieldPredicatePairs); + public abstract void test(final ClassAndFieldPredicatePair baseClassAndFieldPredicatePair, + final ClassAndFieldPredicatePair... classAndFieldPredicatePairs); public void testAll(final Class... classes) { final ClassAndFieldPredicatePair[] classesAndFieldPredicatesPairs = Arrays.stream(classes) @@ -64,12 +64,12 @@ public void testAll(final ClassAndFieldPredicatePair... classesAndFieldPredicate public void setFieldValuesChanger(final AbstractFieldValueChanger fieldValuesChanger) { this.fieldValuesChanger = fieldValuesChanger; - objectGenerator = new ObjectGenerator(fieldValuesChanger, constructorParameters, permutator); + objectGenerator = new ObjectGenerator(fieldValuesChanger, instantiators, permutator); } - public void setUserDefinedConstructors(final MultiValuedMap, ConstructorParameters> constructorParameters) { - this.constructorParameters = constructorParameters; - objectGenerator = new ObjectGenerator(fieldValuesChanger, constructorParameters, permutator); + public void setUserDefinedInstantiators(final List instantiators) { + this.instantiators = instantiators; + objectGenerator = new ObjectGenerator(fieldValuesChanger, instantiators, permutator); } @Override @@ -86,7 +86,7 @@ public boolean equals(final Object otherObject) { return new EqualsBuilder().append(objectGenerator, that.objectGenerator) .append(testAssertions, that.testAssertions) - .append(constructorParameters, that.constructorParameters) + .append(instantiators, that.instantiators) .append(fieldValuesChanger, that.fieldValuesChanger) .isEquals(); } @@ -95,15 +95,11 @@ public boolean equals(final Object otherObject) { public int hashCode() { return new HashCodeBuilder().append(objectGenerator) .append(testAssertions) - .append(constructorParameters) + .append(instantiators) .append(fieldValuesChanger) .toHashCode(); } - protected MultiValuedMap, ConstructorParameters> getConstructorParameters() { - return constructorParameters; - } - @Override public String toString() { return this.getClass() diff --git a/src/main/java/pl/pojo/tester/internal/tester/ConstructorTester.java b/src/main/java/pl/pojo/tester/internal/tester/ConstructorTester.java index fcca0726..a4977dc7 100644 --- a/src/main/java/pl/pojo/tester/internal/tester/ConstructorTester.java +++ b/src/main/java/pl/pojo/tester/internal/tester/ConstructorTester.java @@ -4,15 +4,12 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import pl.pojo.tester.api.ClassAndFieldPredicatePair; -import pl.pojo.tester.api.ConstructorParameters; import pl.pojo.tester.internal.field.AbstractFieldValueChanger; import java.lang.reflect.Constructor; import java.lang.reflect.Modifier; import java.util.Arrays; -import java.util.Collection; import java.util.List; -import java.util.function.Predicate; import java.util.stream.Collectors; public class ConstructorTester extends AbstractTester { @@ -28,11 +25,12 @@ public ConstructorTester(final AbstractFieldValueChanger abstractFieldValueChang } @Override - public void test(final ClassAndFieldPredicatePair baseClassAndFieldPredicatePair, final ClassAndFieldPredicatePair... classAndFieldPredicatePairs) { + public void test(final ClassAndFieldPredicatePair baseClassAndFieldPredicatePair, + final ClassAndFieldPredicatePair... classAndFieldPredicatePairs) { final Class testedClass = baseClassAndFieldPredicatePair.getClazz(); if (isAbstract(testedClass)) { LOGGER.info("Tried to test constructor in abstract ({}) class, annotation or interface. " - + "Skipping due to nature of constructors in those classes", testedClass); + + "Skipping due to nature of constructors in those classes", testedClass); return; } final List> declaredConstructors = getNotSyntheticConstructorFromClass(testedClass); @@ -51,40 +49,12 @@ private boolean isNotSynthetic(final Constructor constructor) { } private void tryInstantiate(final Constructor constructor) { - final Object[] parameters; - final Predicate matchingConstructorParameterTypes = ctr -> ctr.matches(constructor.getParameterTypes()); - - if (constructorParametersAreProvided(constructor)) { - final Collection constructorParameters = getConstructorParameters(constructor); - parameters = constructorParameters.stream() - .filter(matchingConstructorParameterTypes) - .map(ConstructorParameters::getParameters) - .findFirst() - .orElseGet(() -> logAndTryToCreateOwnParameters(constructor)); - } else { - parameters = createConstructorParameters(constructor); - } + final Object[] parameters = createConstructorParameters(constructor); testAssertions.assertThatConstructor(constructor) .willInstantiateClassUsing(parameters); } - private Object[] logAndTryToCreateOwnParameters(final Constructor constructor) { - LOGGER.warn("Class '{}' could not be created by constructor '{}' and any user defined parameters.", - constructor.getDeclaringClass(), - constructor); - return createConstructorParameters(constructor); - } - - private Collection getConstructorParameters(final Constructor constructor) { - return getConstructorParameters().get(constructor.getDeclaringClass()); - } - - private boolean constructorParametersAreProvided(final Constructor constructor) { - final Class declaringClass = constructor.getDeclaringClass(); - return getConstructorParameters().containsKey(declaringClass); - } - private Object[] createConstructorParameters(final Constructor constructor) { return Arrays.stream(constructor.getParameterTypes()) .map(objectGenerator::createNewInstance) diff --git a/src/test/java/helpers/MultiValuedMapMatcher.java b/src/test/java/helpers/MultiValuedMapMatcher.java deleted file mode 100644 index 652b666b..00000000 --- a/src/test/java/helpers/MultiValuedMapMatcher.java +++ /dev/null @@ -1,35 +0,0 @@ -package helpers; - -import org.apache.commons.collections4.MultiValuedMap; -import org.mockito.ArgumentMatcher; -import pl.pojo.tester.api.ConstructorParameters; - -import java.util.Arrays; - -public class MultiValuedMapMatcher implements ArgumentMatcher, ConstructorParameters>> { - - private final Class expectedClass; - private final ConstructorParameters expectedArguments; - - public MultiValuedMapMatcher(final Class expectedClass, final ConstructorParameters expectedArguments) { - this.expectedClass = expectedClass; - this.expectedArguments = expectedArguments; - } - - - @Override - public boolean matches(final MultiValuedMap, ConstructorParameters> argument) { - if (!argument.containsKey(expectedClass)) { - return false; - } - return argument.get(expectedClass) - .stream() - .map(actualArgument -> Arrays.equals(actualArgument.getParameters(), - expectedArguments.getParameters()) - && - Arrays.equals(actualArgument.getParametersTypes(), - expectedArguments.getParametersTypes())) - .findAny() - .isPresent(); - } -} diff --git a/src/test/java/pl/pojo/tester/api/assertion/AbstractAssertionTest.java b/src/test/java/pl/pojo/tester/api/assertion/AbstractAssertionTest.java index 61b9a553..a7413407 100644 --- a/src/test/java/pl/pojo/tester/api/assertion/AbstractAssertionTest.java +++ b/src/test/java/pl/pojo/tester/api/assertion/AbstractAssertionTest.java @@ -1,7 +1,6 @@ package pl.pojo.tester.api.assertion; import classesForTest.fields.TestEnum1; -import helpers.MultiValuedMapMatcher; import org.apache.commons.lang3.builder.EqualsBuilder; import org.apache.commons.lang3.builder.HashCodeBuilder; import org.apache.commons.lang3.builder.ToStringBuilder; @@ -10,16 +9,22 @@ import pl.pojo.tester.internal.assertion.AbstractAssertionError; import pl.pojo.tester.internal.field.AbstractFieldValueChanger; import pl.pojo.tester.internal.field.DefaultFieldValueChanger; -import pl.pojo.tester.internal.utils.SublistFieldPermutator; +import pl.pojo.tester.internal.instantiator.UserDefinedConstructorInstantiator; import pl.pojo.tester.internal.tester.EqualsTester; import pl.pojo.tester.internal.tester.HashCodeTester; import pl.pojo.tester.internal.utils.CollectionUtils; +import pl.pojo.tester.internal.utils.SublistFieldPermutator; import java.util.Random; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.catchThrowable; -import static org.mockito.Mockito.*; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; import static org.powermock.reflect.Whitebox.getInternalState; import static org.powermock.reflect.Whitebox.setInternalState; @@ -149,24 +154,25 @@ void Should_Set_Field_Value_Changer_To_Testers() { } @Test - void Should_Set_User_Defined_Class_And_Constructor_Parameters_To_Tester() { + void Should_Set_Instantiators_To_Tester() { // given final AbstractAssertion abstractAssertion = new AbstractAssertionImplementation(); final EqualsTester equalsTester = mock(EqualsTester.class); setInternalState(abstractAssertion, "testers", CollectionUtils.asSet(equalsTester)); final Class expectedClass = String.class; - final Object[] expectedArguments = {'c', 'h', 'a', 'r'}; - final Class[] expectedTypes = {char.class, char.class, char.class, char.class}; - final ConstructorParameters expectedConstructorParameters = new ConstructorParameters(expectedArguments, - expectedTypes); - abstractAssertion.create(expectedClass, expectedConstructorParameters); + final Object[] expectedArguments = { 'c', 'h', 'a', 'r' }; + final Class[] expectedTypes = { char.class, char.class, char.class, char.class }; + final ConstructorParameters constructorParameters = new ConstructorParameters(expectedArguments, + expectedTypes); + final UserDefinedConstructorInstantiator instantiator = new UserDefinedConstructorInstantiator(expectedClass, + constructorParameters); + abstractAssertion.create(expectedClass, instantiator::instantiate); // when abstractAssertion.areWellImplemented(); // then - verify(equalsTester, times(1)).setUserDefinedConstructors(argThat(new MultiValuedMapMatcher(expectedClass, - expectedConstructorParameters))); + verify(equalsTester, times(1)).setUserDefinedInstantiators(any()); } @Test @@ -176,8 +182,8 @@ void Should_Call_Next_Create_Method() { final EqualsTester equalsTester = mock(EqualsTester.class); setInternalState(abstractAssertion, "testers", CollectionUtils.asSet(equalsTester)); final Class expectedClass = String.class; - final Object[] expectedArguments = {'c', 'h', 'a', 'r'}; - final Class[] expectedTypes = {char.class, char.class, char.class, char.class}; + final Object[] expectedArguments = { 'c', 'h', 'a', 'r' }; + final Class[] expectedTypes = { char.class, char.class, char.class, char.class }; final ConstructorParameters expectedConstructorParameters = new ConstructorParameters(expectedArguments, expectedTypes); abstractAssertion.create(expectedClass, expectedArguments, expectedTypes); @@ -189,35 +195,14 @@ void Should_Call_Next_Create_Method() { verify(abstractAssertion).create(eq(expectedClass), eq(expectedConstructorParameters)); } - @Test - void Should_Set_User_Defined_Class_And_Constructor_Parameters_To_Tester_Using_Class_Name() { - // given - final AbstractAssertion abstractAssertion = new AbstractAssertionImplementation(); - final EqualsTester equalsTester = mock(EqualsTester.class); - setInternalState(abstractAssertion, "testers", CollectionUtils.asSet(equalsTester)); - final Class expectedClass = String.class; - final Object[] expectedArguments = {'c', 'h', 'a', 'r'}; - final Class[] expectedTypes = {char.class, char.class, char.class, char.class}; - final ConstructorParameters expectedConstructorParameters = new ConstructorParameters(expectedArguments, - expectedTypes); - abstractAssertion.create("java.lang.String", expectedConstructorParameters); - - // when - abstractAssertion.areWellImplemented(); - - // then - verify(equalsTester, times(1)).setUserDefinedConstructors(argThat(new MultiValuedMapMatcher(expectedClass, - expectedConstructorParameters))); - } - @Test void Should_Call_Next_Create_Method_Using_Class_Name() { // given final AbstractAssertion abstractAssertion = spy(new AbstractAssertionImplementation()); final EqualsTester equalsTester = mock(EqualsTester.class); setInternalState(abstractAssertion, "testers", CollectionUtils.asSet(equalsTester)); - final Object[] expectedArguments = {'c', 'h', 'a', 'r'}; - final Class[] expectedTypes = {char.class, char.class, char.class, char.class}; + final Object[] expectedArguments = { 'c', 'h', 'a', 'r' }; + final Class[] expectedTypes = { char.class, char.class, char.class, char.class }; final ConstructorParameters expectedConstructorParameters = new ConstructorParameters(expectedArguments, expectedTypes); final String expectedClassName = "java.lang.String"; diff --git a/src/test/java/pl/pojo/tester/internal/instantiator/AbstractMultiConstructorInstantiatorTest.java b/src/test/java/pl/pojo/tester/internal/instantiator/AbstractMultiConstructorInstantiatorTest.java index f2f8c83b..4c743783 100644 --- a/src/test/java/pl/pojo/tester/internal/instantiator/AbstractMultiConstructorInstantiatorTest.java +++ b/src/test/java/pl/pojo/tester/internal/instantiator/AbstractMultiConstructorInstantiatorTest.java @@ -1,12 +1,10 @@ package pl.pojo.tester.internal.instantiator; import lombok.Data; -import org.apache.commons.collections4.MultiValuedMap; -import org.apache.commons.collections4.multimap.ArrayListValuedHashMap; import org.junit.jupiter.api.Test; -import pl.pojo.tester.api.ConstructorParameters; import java.lang.reflect.Constructor; +import java.util.LinkedList; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.catchThrowable; @@ -14,45 +12,11 @@ class AbstractMultiConstructorInstantiatorTest { - @Test - void Should_Create_Object_Using_User_Parameters() { - // given - final ArrayListValuedHashMap, ConstructorParameters> constructorParameters = new ArrayListValuedHashMap<>(); - final Class clazz = A.class; - constructorParameters.put(clazz, new ConstructorParameters(new Object[]{ 12345 }, new Class[]{ int.class })); - final AbstractMultiConstructorInstantiator instantiator = new MockMultiConstructorInstantiator(clazz, - constructorParameters); - final A expectedResult = new A(12345); - - // when - final Object result = instantiator.instantiateUsingUserParameters(); - - // then - assertThat(result).isEqualTo(expectedResult); - } - - @Test - void Should_Return_Null_If_Parameters_For_This_Class_Are_Empty() { - // given - final ArrayListValuedHashMap, ConstructorParameters> constructorParameters = new ArrayListValuedHashMap<>(); - final Class clazz = A.class; - final AbstractMultiConstructorInstantiator instantiator = new MockMultiConstructorInstantiator(clazz, - constructorParameters); - - // when - final Object result = instantiator.instantiateUsingUserParameters(); - - // then - assertThat(result).isNull(); - } - @Test void Should_Throw_Exception_If_Constructor_Throws_Exception() { // given - final ArrayListValuedHashMap, ConstructorParameters> constructorParameters = new ArrayListValuedHashMap<>(); final Class clazz = B.class; - final AbstractMultiConstructorInstantiator instantiator = new MockMultiConstructorInstantiator(clazz, - constructorParameters); + final AbstractMultiConstructorInstantiator instantiator = new MockMultiConstructorInstantiator(clazz); final Throwable expectedResult = new ObjectInstantiationException(B.class, "msg", null); // when @@ -63,9 +27,8 @@ void Should_Throw_Exception_If_Constructor_Throws_Exception() { } static class MockMultiConstructorInstantiator extends AbstractMultiConstructorInstantiator { - MockMultiConstructorInstantiator(final Class clazz, - final MultiValuedMap, ConstructorParameters> constructorParameters) { - super(clazz, constructorParameters); + MockMultiConstructorInstantiator(final Class clazz) { + super(clazz, new LinkedList<>()); } @Override diff --git a/src/test/java/pl/pojo/tester/internal/instantiator/ArrayInstantiatorTest.java b/src/test/java/pl/pojo/tester/internal/instantiator/ArrayInstantiatorTest.java index 8eb7a755..c8d0db7f 100644 --- a/src/test/java/pl/pojo/tester/internal/instantiator/ArrayInstantiatorTest.java +++ b/src/test/java/pl/pojo/tester/internal/instantiator/ArrayInstantiatorTest.java @@ -1,7 +1,6 @@ package pl.pojo.tester.internal.instantiator; -import org.apache.commons.collections4.multimap.ArrayListValuedHashMap; import org.junit.jupiter.api.DynamicTest; import org.junit.jupiter.api.TestFactory; import org.junit.jupiter.api.function.Executable; @@ -39,8 +38,7 @@ Stream Should_Create_Array_By_Class() { private Executable Should_Create_Array(final Class classToInstantiate) { return () -> { // given - final ArrayInstantiator instantiator = new ArrayInstantiator(classToInstantiate, - new ArrayListValuedHashMap<>()); + final ArrayInstantiator instantiator = new ArrayInstantiator(classToInstantiate); // when final Object result = instantiator.instantiate(); diff --git a/src/test/java/pl/pojo/tester/internal/instantiator/BestConstructorInstantiatorTest.java b/src/test/java/pl/pojo/tester/internal/instantiator/BestConstructorInstantiatorTest.java index 04065a18..9da43fb5 100644 --- a/src/test/java/pl/pojo/tester/internal/instantiator/BestConstructorInstantiatorTest.java +++ b/src/test/java/pl/pojo/tester/internal/instantiator/BestConstructorInstantiatorTest.java @@ -1,19 +1,27 @@ package pl.pojo.tester.internal.instantiator; -import classesForTest.*; +import classesForTest.ClassContainingStaticClasses; +import classesForTest.Constructor_Stream; +import classesForTest.Constructor_Thread; +import classesForTest.Constructors_First_Throws_Exception; +import classesForTest.PackageConstructor; +import classesForTest.Person; +import classesForTest.PrivateConstructor; +import classesForTest.ProtectedConstructor; import lombok.EqualsAndHashCode; import lombok.ToString; -import org.apache.commons.collections4.MultiValuedMap; -import org.apache.commons.collections4.multimap.ArrayListValuedHashMap; import org.junit.jupiter.api.DynamicTest; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestFactory; import org.junit.jupiter.api.function.Executable; +import pl.pojo.tester.api.AbstractObjectInstantiator; import pl.pojo.tester.api.ConstructorParameters; import pl.pojo.tester.api.FieldPredicate; import pl.pojo.tester.internal.utils.FieldUtils; import pl.pojo.tester.internal.utils.MethodUtils; +import java.util.ArrayList; +import java.util.List; import java.util.stream.Stream; import static helpers.TestHelper.getDefaultDisplayName; @@ -24,8 +32,6 @@ class BestConstructorInstantiatorTest { - private final MultiValuedMap, ConstructorParameters> constructorParameters = new ArrayListValuedHashMap<>(); - @TestFactory Stream Should_Instantiate_Non_Public_Classes() { return Stream.of("classesForTest.UnpublicClass", @@ -62,7 +68,7 @@ private Executable Should_Instantiate_Non_Public_Classes(final String className) // given final Class classUnderTest = Class.forName(className); final BestConstructorInstantiator instantiator = new BestConstructorInstantiator(classUnderTest, - constructorParameters); + new ArrayList<>()); // when final Object result = instantiator.instantiate(); @@ -113,7 +119,7 @@ private Executable Should_Create_Object_Using_Best_Constructor(final Class cl return () -> { // given final BestConstructorInstantiator instantiator = new BestConstructorInstantiator(classToInstantiate, - constructorParameters); + new ArrayList<>()); // when final Object result = instantiator.instantiate(); @@ -135,7 +141,7 @@ private Executable Should_Throw_Exception_When_Cannot_Instantiate_Class(final Cl return () -> { // given final BestConstructorInstantiator instantiator = new BestConstructorInstantiator(classToInstantiate, - constructorParameters); + new ArrayList<>()); // when final Throwable result = catchThrowable(instantiator::instantiate); @@ -150,7 +156,7 @@ void Should_Create_Object_Using_Private_Constructor() { // given final Class classToInstantiate = PrivateConstructor.class; final BestConstructorInstantiator instantiator = new BestConstructorInstantiator(classToInstantiate, - constructorParameters); + new ArrayList<>()); // when final Object result = instantiator.instantiate(); @@ -164,7 +170,7 @@ void Should_Create_Object_With_Second_Constructor_If_First_Threw_exception() { // given final Class classToInstantiate = Constructors_First_Throws_Exception.class; final BestConstructorInstantiator instantiator = new BestConstructorInstantiator(classToInstantiate, - constructorParameters); + new ArrayList<>()); // when final Object result = instantiator.instantiate(); @@ -176,12 +182,12 @@ void Should_Create_Object_With_Second_Constructor_If_First_Threw_exception() { @Test void Should_Create_Object_With_User_Defined_Constructor_Parameters() { // given - final ArrayListValuedHashMap, ConstructorParameters> constructorParameters = new ArrayListValuedHashMap<>(); - final ConstructorParameters parameters = new ConstructorParameters(new Object[]{"expectedString"}, - new Class[]{Object.class}); - constructorParameters.put(NoDefaultConstructor.class, parameters); + final List instantiators = new ArrayList<>(); + final ConstructorParameters parameters = new ConstructorParameters(new Object[]{ "expectedString" }, + new Class[]{ Object.class }); + instantiators.add(new UserDefinedConstructorInstantiator(NoDefaultConstructor.class, parameters)); final BestConstructorInstantiator instantiator = new BestConstructorInstantiator(NoDefaultConstructor.class, - constructorParameters); + instantiators); final NoDefaultConstructor expectedResult = new NoDefaultConstructor("expectedString"); diff --git a/src/test/java/pl/pojo/tester/internal/instantiator/CollectionInstantiatorTest.java b/src/test/java/pl/pojo/tester/internal/instantiator/CollectionInstantiatorTest.java index 65af4e20..ddc91515 100644 --- a/src/test/java/pl/pojo/tester/internal/instantiator/CollectionInstantiatorTest.java +++ b/src/test/java/pl/pojo/tester/internal/instantiator/CollectionInstantiatorTest.java @@ -1,6 +1,5 @@ package pl.pojo.tester.internal.instantiator; -import org.apache.commons.collections4.multimap.ArrayListValuedHashMap; import org.junit.jupiter.api.DynamicTest; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestFactory; @@ -71,8 +70,7 @@ Stream Should_Return_Expected_Collection_Object() { private Executable Should_Return_Expected_Collection_Object(final Class classToInstantiate) { return () -> { // given - final CollectionInstantiator instantiator = new CollectionInstantiator(classToInstantiate, - new ArrayListValuedHashMap<>()); + final CollectionInstantiator instantiator = new CollectionInstantiator(classToInstantiate); // when final Object result = instantiator.instantiate(); @@ -85,8 +83,7 @@ private Executable Should_Return_Expected_Collection_Object(final Class class @Test void Should_Throws_Exception_When_Prepared_Objects_Do_Not_Contain_Expected_Class() { // given - final CollectionInstantiator instantiator = new CollectionInstantiator(String.class, - new ArrayListValuedHashMap<>()); + final CollectionInstantiator instantiator = new CollectionInstantiator(String.class); // when final Throwable result = catchThrowable(instantiator::instantiate); diff --git a/src/test/java/pl/pojo/tester/internal/instantiator/DefaultConstructorInstantiatorTest.java b/src/test/java/pl/pojo/tester/internal/instantiator/DefaultConstructorInstantiatorTest.java index a2833fdd..b9366fb6 100644 --- a/src/test/java/pl/pojo/tester/internal/instantiator/DefaultConstructorInstantiatorTest.java +++ b/src/test/java/pl/pojo/tester/internal/instantiator/DefaultConstructorInstantiatorTest.java @@ -1,7 +1,6 @@ package pl.pojo.tester.internal.instantiator; -import org.apache.commons.collections4.multimap.ArrayListValuedHashMap; import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.assertThat; @@ -14,8 +13,7 @@ class DefaultConstructorInstantiatorTest { void Should_Create_Object_Using_Default_Constructor() { // given final Class classToInstantiate = String.class; - final DefaultConstructorInstantiator instantiator = new DefaultConstructorInstantiator(classToInstantiate, - new ArrayListValuedHashMap<>()); + final DefaultConstructorInstantiator instantiator = new DefaultConstructorInstantiator(classToInstantiate); // when final Object result = instantiator.instantiate(); @@ -28,8 +26,7 @@ void Should_Create_Object_Using_Default_Constructor() { void Should_Throw_Exception_When_Cannot_Instantiate_Object() { // given final Class classToInstantiate = No_Args_Constructor_Throws_IllegalAccessException.class; - final DefaultConstructorInstantiator instantiator = new DefaultConstructorInstantiator(classToInstantiate, - new ArrayListValuedHashMap<>()); + final DefaultConstructorInstantiator instantiator = new DefaultConstructorInstantiator(classToInstantiate); // when final Throwable result = catchThrowable(instantiator::instantiate); diff --git a/src/test/java/pl/pojo/tester/internal/instantiator/EnumInstantiatorTest.java b/src/test/java/pl/pojo/tester/internal/instantiator/EnumInstantiatorTest.java index f4f1d243..0d8efa69 100644 --- a/src/test/java/pl/pojo/tester/internal/instantiator/EnumInstantiatorTest.java +++ b/src/test/java/pl/pojo/tester/internal/instantiator/EnumInstantiatorTest.java @@ -2,7 +2,6 @@ import classesForTest.EmptyEnum; -import org.apache.commons.collections4.multimap.ArrayListValuedHashMap; import org.junit.jupiter.api.Test; import static org.assertj.core.api.Assertions.assertThat; @@ -13,7 +12,7 @@ public class EnumInstantiatorTest { @Test void Should_Return_Null_When_Enum_Is_Empty() { // given - final EnumInstantiator instantiator = new EnumInstantiator(EmptyEnum.class, new ArrayListValuedHashMap<>()); + final EnumInstantiator instantiator = new EnumInstantiator(EmptyEnum.class); // when final Object result = instantiator.instantiate(); @@ -26,7 +25,7 @@ void Should_Return_Null_When_Enum_Is_Empty() { void Should_Return_Any_Enum_Value() { // given final Class doubleEnumClass = DoubleEnum.class; - final EnumInstantiator instantiator = new EnumInstantiator(doubleEnumClass, new ArrayListValuedHashMap<>()); + final EnumInstantiator instantiator = new EnumInstantiator(doubleEnumClass); // when final Object result = instantiator.instantiate(); @@ -39,7 +38,7 @@ void Should_Return_Any_Enum_Value() { void Should_Return_One_Enum_Value() { // given final Class oneEnumClass = OneEnum.class; - final EnumInstantiator instantiator = new EnumInstantiator(oneEnumClass, new ArrayListValuedHashMap<>()); + final EnumInstantiator instantiator = new EnumInstantiator(oneEnumClass); // when final Object result = instantiator.instantiate(); diff --git a/src/test/java/pl/pojo/tester/internal/instantiator/InstantiableTest.java b/src/test/java/pl/pojo/tester/internal/instantiator/InstantiableTest.java index 9a8e0a71..375d8a50 100644 --- a/src/test/java/pl/pojo/tester/internal/instantiator/InstantiableTest.java +++ b/src/test/java/pl/pojo/tester/internal/instantiator/InstantiableTest.java @@ -7,14 +7,12 @@ import classesForTest.EmptyEnum; import lombok.AllArgsConstructor; import lombok.Data; -import org.apache.commons.collections4.MultiValuedMap; -import org.apache.commons.collections4.multimap.ArrayListValuedHashMap; import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.DynamicTest; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestFactory; import org.junit.jupiter.api.function.Executable; -import pl.pojo.tester.api.ConstructorParameters; +import pl.pojo.tester.api.AbstractObjectInstantiator; import pl.pojo.tester.internal.field.date.DefaultDateAndTimeFieldValueChanger; import java.io.Serializable; @@ -49,11 +47,11 @@ class InstantiableTest { - private static final MultiValuedMap, ConstructorParameters> CLASS_AND_CONSTRUCTOR_PARAMETERS = new ArrayListValuedHashMap<>(); + private static final List INSTANTIATORS = new LinkedList<>(); @BeforeAll static void beforeAll() { - CLASS_AND_CONSTRUCTOR_PARAMETERS.put(UserDefinedClass.class, null); + INSTANTIATORS.add(new SupplierInstantiator(UserDefinedClass.class, () -> null)); } @TestFactory @@ -69,7 +67,7 @@ Stream Should_Return_Expected_Instantiator_For_Class() { new ClassInstantiator(Constructor_Stream.class, BestConstructorInstantiator.class), new ClassInstantiator(Constructor_Thread.class, BestConstructorInstantiator.class), new ClassInstantiator(String.class, JavaTypeInstantiator.class), - new ClassInstantiator(UserDefinedClass.class, UserDefinedConstructorInstantiator.class), + new ClassInstantiator(UserDefinedClass.class, SupplierInstantiator.class), new ClassInstantiator(Boolean[].class, ArrayInstantiator.class), new ClassInstantiator(Byte[].class, ArrayInstantiator.class), new ClassInstantiator(Character[].class, ArrayInstantiator.class), @@ -146,7 +144,7 @@ Stream Should_Return_Expected_Instantiator_For_Class() { private Executable Should_Return_Expected_Instantiator_For_Class(final ClassInstantiator testCase) { return () -> { // when - final Object result = Instantiable.forClass(testCase.clazz, CLASS_AND_CONSTRUCTOR_PARAMETERS); + final Object result = Instantiable.forClass(testCase.clazz, INSTANTIATORS); // then assertThat(result).isInstanceOf(testCase.instantiator); @@ -159,7 +157,7 @@ void Should_Instantiate_Two_Classes() { final Class[] classesToInstantiate = { A.class, B.class }; // when - final Object[] result = Instantiable.instantiateClasses(classesToInstantiate, new ArrayListValuedHashMap<>()); + final Object[] result = Instantiable.instantiateClasses(classesToInstantiate, new ArrayList<>()); // then assertThat(result).extracting(Object::getClass) @@ -167,28 +165,27 @@ void Should_Instantiate_Two_Classes() { } @Test - void Should_Return_User_Defined_Constructor_Instantiator_If_Class_Does_Not_Qualifies_For_Proxy_And() { + void Should_Return_Instantiator_Defined_By_User() { // given - final ArrayListValuedHashMap, ConstructorParameters> constructorParameters = new ArrayListValuedHashMap<>(); + final List instantiators = new ArrayList<>(); final Class clazz = A.class; - constructorParameters.put(clazz, new ConstructorParameters(new Object[0], new Class[0])); + final SupplierInstantiator expectedInstantiator = new SupplierInstantiator(clazz, () -> new Object[0]); + instantiators.add(expectedInstantiator); // when - final AbstractObjectInstantiator result = Instantiable.forClass(clazz, constructorParameters); + final AbstractObjectInstantiator result = Instantiable.forClass(clazz, instantiators); // then - assertThat(result).isInstanceOf(UserDefinedConstructorInstantiator.class); + assertThat(result).isEqualTo(expectedInstantiator); } @Test - void Should_Return_Proxy_Instantiator_If_Class_Qualifies_For_Proxy_And_User_Defined_Constructor_Parameters() { + void Should_Return_Proxy_Instantiator_If_Class_Qualifies_For_Proxy() { // given - final ArrayListValuedHashMap, ConstructorParameters> constructorParameters = new ArrayListValuedHashMap<>(); final Class clazz = Abstract.class; - constructorParameters.put(clazz, new ConstructorParameters(new Object[0], new Class[0])); // when - final AbstractObjectInstantiator result = Instantiable.forClass(clazz, constructorParameters); + final AbstractObjectInstantiator result = Instantiable.forClass(clazz, new ArrayList<>()); // then assertThat(result).isInstanceOf(ProxyInstantiator.class); diff --git a/src/test/java/pl/pojo/tester/internal/instantiator/JavaTypeInstantiatorTest.java b/src/test/java/pl/pojo/tester/internal/instantiator/JavaTypeInstantiatorTest.java index e4e00488..a9efea71 100644 --- a/src/test/java/pl/pojo/tester/internal/instantiator/JavaTypeInstantiatorTest.java +++ b/src/test/java/pl/pojo/tester/internal/instantiator/JavaTypeInstantiatorTest.java @@ -1,6 +1,5 @@ package pl.pojo.tester.internal.instantiator; -import org.apache.commons.collections4.multimap.ArrayListValuedHashMap; import org.junit.jupiter.api.DynamicTest; import org.junit.jupiter.api.TestFactory; import org.junit.jupiter.api.function.Executable; @@ -57,8 +56,7 @@ Stream Should_Instantiate_Primitive() { private Executable Should_Instantiate_Primitive(final Class classToInstantiate) { return () -> { // given - final JavaTypeInstantiator instantiator = new JavaTypeInstantiator(classToInstantiate, - new ArrayListValuedHashMap<>()); + final JavaTypeInstantiator instantiator = new JavaTypeInstantiator(classToInstantiate); // when final Object result = instantiator.instantiate(); @@ -107,8 +105,7 @@ Stream Should_Instantiate_Java_Type_Classes() { private Executable Should_Instantiate_Java_Type_Classes(final Class classToInstantiate) { return () -> { // given - final JavaTypeInstantiator instantiator = new JavaTypeInstantiator(classToInstantiate, - new ArrayListValuedHashMap<>()); + final JavaTypeInstantiator instantiator = new JavaTypeInstantiator(classToInstantiate); // when final Object result = instantiator.instantiate(); diff --git a/src/test/java/pl/pojo/tester/internal/instantiator/ObjectGeneratorFastTest.java b/src/test/java/pl/pojo/tester/internal/instantiator/ObjectGeneratorFastTest.java index c57a7de0..26fca4e4 100644 --- a/src/test/java/pl/pojo/tester/internal/instantiator/ObjectGeneratorFastTest.java +++ b/src/test/java/pl/pojo/tester/internal/instantiator/ObjectGeneratorFastTest.java @@ -14,8 +14,6 @@ import lombok.Getter; import lombok.Setter; import lombok.ToString; -import org.apache.commons.collections4.MultiValuedMap; -import org.apache.commons.collections4.multimap.ArrayListValuedHashMap; import org.apache.commons.lang3.builder.EqualsBuilder; import org.apache.commons.lang3.builder.HashCodeBuilder; import org.apache.commons.lang3.builder.ToStringBuilder; @@ -24,11 +22,11 @@ import org.junit.jupiter.api.TestFactory; import org.junit.jupiter.api.function.Executable; import pl.pojo.tester.api.ClassAndFieldPredicatePair; -import pl.pojo.tester.api.ConstructorParameters; import pl.pojo.tester.internal.field.AbstractFieldValueChanger; import pl.pojo.tester.internal.field.DefaultFieldValueChanger; import pl.pojo.tester.internal.utils.SublistFieldPermutator; +import java.util.LinkedList; import java.util.List; import java.util.Random; import java.util.UUID; @@ -42,18 +40,15 @@ class ObjectGeneratorFastTest { private final AbstractFieldValueChanger abstractFieldValueChanger = DefaultFieldValueChanger.INSTANCE; - private final MultiValuedMap, ConstructorParameters> constructorParameters = new - ArrayListValuedHashMap<>(); - private ObjectGenerator makeObjectGenerator(final AbstractFieldValueChanger abstractFieldValueChanger, - final MultiValuedMap, ConstructorParameters> constructorParameters) { - return new ObjectGenerator(abstractFieldValueChanger, constructorParameters, new SublistFieldPermutator()); + private ObjectGenerator makeObjectGenerator(final AbstractFieldValueChanger abstractFieldValueChanger) { + return new ObjectGenerator(abstractFieldValueChanger, new LinkedList<>(), new SublistFieldPermutator()); } @Test void Should_Generate_Different_Objects_For_Class_Containing_Boolean_Type() { // given - final ObjectGenerator objectGenerator = makeObjectGenerator(abstractFieldValueChanger, constructorParameters); + final ObjectGenerator objectGenerator = makeObjectGenerator(abstractFieldValueChanger); final ClassAndFieldPredicatePair classAndFieldPredicatePair = new ClassAndFieldPredicatePair( ClassWithBooleanField.class); @@ -68,7 +63,7 @@ void Should_Generate_Different_Objects_For_Class_Containing_Boolean_Type() { @Test void Should_Generate_Different_Objects_For_Class_With_Private_Enum() { // given - final ObjectGenerator objectGenerator = makeObjectGenerator(abstractFieldValueChanger, constructorParameters); + final ObjectGenerator objectGenerator = makeObjectGenerator(abstractFieldValueChanger); final ClassAndFieldPredicatePair classAndFieldPredicatePair = new ClassAndFieldPredicatePair( ClassContainingPrivateEnum.class); @@ -83,7 +78,7 @@ void Should_Generate_Different_Objects_For_Class_With_Private_Enum() { @Test void Should_Create_Any_Instance() { // given - final ObjectGenerator objectGenerator = makeObjectGenerator(abstractFieldValueChanger, constructorParameters); + final ObjectGenerator objectGenerator = makeObjectGenerator(abstractFieldValueChanger); final Class expectedClass = GoodPojo_Equals_HashCode_ToString.class; // when @@ -105,8 +100,7 @@ Stream Should_Create_Same_Instance() { private Executable Should_Create_Same_Instance(final Object objectToCreateSameInstance) { return () -> { // given - final ObjectGenerator objectGenerator = makeObjectGenerator(abstractFieldValueChanger, - constructorParameters); + final ObjectGenerator objectGenerator = makeObjectGenerator(abstractFieldValueChanger); // when final Object result = objectGenerator.generateSameInstance(objectToCreateSameInstance); @@ -150,8 +144,7 @@ Stream Should_Generate_Different_Objects() { private Executable Should_Generate_Different_Objects(final DifferentObjectTestCase testCase) { return () -> { // given - final ObjectGenerator objectGenerator = makeObjectGenerator(abstractFieldValueChanger, - constructorParameters); + final ObjectGenerator objectGenerator = makeObjectGenerator(abstractFieldValueChanger); final ClassAndFieldPredicatePair classAndFieldPredicatePair = new ClassAndFieldPredicatePair(testCase.clazz); // when @@ -189,8 +182,7 @@ Stream Should_Generate_Different_Objects_Recursively() { public Executable Should_Generate_Different_Objects_Recursively(final RecursivelyDifferentObjectTestCase testCase) { return () -> { // given - final ObjectGenerator objectGenerator = makeObjectGenerator(abstractFieldValueChanger, - constructorParameters); + final ObjectGenerator objectGenerator = makeObjectGenerator(abstractFieldValueChanger); // when final List result = objectGenerator.generateDifferentObjects(testCase.baseClass, @@ -205,7 +197,7 @@ public Executable Should_Generate_Different_Objects_Recursively(final Recursivel @Test void Should_Not_Fall_In_Endless_Loop() { // given - final ObjectGenerator objectGenerator = makeObjectGenerator(abstractFieldValueChanger, constructorParameters); + final ObjectGenerator objectGenerator = makeObjectGenerator(abstractFieldValueChanger); final ClassAndFieldPredicatePair iClass = new ClassAndFieldPredicatePair(R.class); final int expectedSize = 2; diff --git a/src/test/java/pl/pojo/tester/internal/instantiator/ObjectGeneratorTest.java b/src/test/java/pl/pojo/tester/internal/instantiator/ObjectGeneratorTest.java index a0e5426d..ad30c411 100644 --- a/src/test/java/pl/pojo/tester/internal/instantiator/ObjectGeneratorTest.java +++ b/src/test/java/pl/pojo/tester/internal/instantiator/ObjectGeneratorTest.java @@ -14,8 +14,6 @@ import lombok.Getter; import lombok.Setter; import lombok.ToString; -import org.apache.commons.collections4.MultiValuedMap; -import org.apache.commons.collections4.multimap.ArrayListValuedHashMap; import org.apache.commons.lang3.builder.EqualsBuilder; import org.apache.commons.lang3.builder.HashCodeBuilder; import org.apache.commons.lang3.builder.ToStringBuilder; @@ -24,11 +22,11 @@ import org.junit.jupiter.api.TestFactory; import org.junit.jupiter.api.function.Executable; import pl.pojo.tester.api.ClassAndFieldPredicatePair; -import pl.pojo.tester.api.ConstructorParameters; import pl.pojo.tester.internal.field.AbstractFieldValueChanger; import pl.pojo.tester.internal.field.DefaultFieldValueChanger; import pl.pojo.tester.internal.utils.ThoroughFieldPermutator; +import java.util.LinkedList; import java.util.List; import java.util.Random; import java.util.UUID; @@ -42,18 +40,15 @@ class ObjectGeneratorTest { private final AbstractFieldValueChanger abstractFieldValueChanger = DefaultFieldValueChanger.INSTANCE; - private final MultiValuedMap, ConstructorParameters> constructorParameters = new - ArrayListValuedHashMap<>(); - private ObjectGenerator makeObjectGenerator(final AbstractFieldValueChanger abstractFieldValueChanger, - final MultiValuedMap, ConstructorParameters> constructorParameters) { - return new ObjectGenerator(abstractFieldValueChanger, constructorParameters, new ThoroughFieldPermutator()); + private ObjectGenerator makeObjectGenerator(final AbstractFieldValueChanger abstractFieldValueChanger) { + return new ObjectGenerator(abstractFieldValueChanger, new LinkedList<>(), new ThoroughFieldPermutator()); } @Test void Should_Generate_Different_Objects_For_Class_Containing_Boolean_Type() { // given - final ObjectGenerator objectGenerator = makeObjectGenerator(abstractFieldValueChanger, constructorParameters); + final ObjectGenerator objectGenerator = makeObjectGenerator(abstractFieldValueChanger); final ClassAndFieldPredicatePair classAndFieldPredicatePair = new ClassAndFieldPredicatePair( ClassWithBooleanField.class); @@ -68,7 +63,7 @@ void Should_Generate_Different_Objects_For_Class_Containing_Boolean_Type() { @Test void Should_Generate_Different_Objects_For_Class_With_Private_Enum() { // given - final ObjectGenerator objectGenerator = makeObjectGenerator(abstractFieldValueChanger, constructorParameters); + final ObjectGenerator objectGenerator = makeObjectGenerator(abstractFieldValueChanger); final ClassAndFieldPredicatePair classAndFieldPredicatePair = new ClassAndFieldPredicatePair( ClassContainingPrivateEnum.class); @@ -83,7 +78,7 @@ void Should_Generate_Different_Objects_For_Class_With_Private_Enum() { @Test void Should_Create_Any_Instance() { // given - final ObjectGenerator objectGenerator = makeObjectGenerator(abstractFieldValueChanger, constructorParameters); + final ObjectGenerator objectGenerator = makeObjectGenerator(abstractFieldValueChanger); final Class expectedClass = GoodPojo_Equals_HashCode_ToString.class; // when @@ -105,8 +100,7 @@ Stream Should_Create_Same_Instance() { private Executable Should_Create_Same_Instance(final Object objectToCreateSameInstance) { return () -> { // given - final ObjectGenerator objectGenerator = makeObjectGenerator(abstractFieldValueChanger, - constructorParameters); + final ObjectGenerator objectGenerator = makeObjectGenerator(abstractFieldValueChanger); // when final Object result = objectGenerator.generateSameInstance(objectToCreateSameInstance); @@ -150,8 +144,7 @@ Stream Should_Generate_Different_Objects() { private Executable Should_Generate_Different_Objects(final DifferentObjectTestCase testCase) { return () -> { // given - final ObjectGenerator objectGenerator = makeObjectGenerator(abstractFieldValueChanger, - constructorParameters); + final ObjectGenerator objectGenerator = makeObjectGenerator(abstractFieldValueChanger); final ClassAndFieldPredicatePair classAndFieldPredicatePair = new ClassAndFieldPredicatePair(testCase.clazz); // when @@ -189,8 +182,7 @@ Stream Should_Generate_Different_Objects_Recursively() { private Executable Should_Generate_Different_Objects_Recursively(final RecursivelyDifferentObjectTestCase testCase) { return () -> { // given - final ObjectGenerator objectGenerator = makeObjectGenerator(abstractFieldValueChanger, - constructorParameters); + final ObjectGenerator objectGenerator = makeObjectGenerator(abstractFieldValueChanger); // when final List result = objectGenerator.generateDifferentObjects(testCase.baseClass, @@ -205,7 +197,7 @@ private Executable Should_Generate_Different_Objects_Recursively(final Recursive @Test void Should_Not_Fall_In_Endless_Loop() { // given - final ObjectGenerator objectGenerator = makeObjectGenerator(abstractFieldValueChanger, constructorParameters); + final ObjectGenerator objectGenerator = makeObjectGenerator(abstractFieldValueChanger); final ClassAndFieldPredicatePair iClass = new ClassAndFieldPredicatePair(R.class); final int expectedSize = 2; diff --git a/src/test/java/pl/pojo/tester/internal/instantiator/ProxyInstantiatorTest.java b/src/test/java/pl/pojo/tester/internal/instantiator/ProxyInstantiatorTest.java index 8bac12ff..98ae1518 100644 --- a/src/test/java/pl/pojo/tester/internal/instantiator/ProxyInstantiatorTest.java +++ b/src/test/java/pl/pojo/tester/internal/instantiator/ProxyInstantiatorTest.java @@ -6,14 +6,12 @@ import classesForTest.Annotation; import classesForTest.Interface; import lombok.Data; -import org.apache.commons.collections4.MultiValuedMap; -import org.apache.commons.collections4.multimap.ArrayListValuedHashMap; import org.junit.jupiter.api.DynamicTest; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestFactory; import org.junit.jupiter.api.function.Executable; -import pl.pojo.tester.api.ConstructorParameters; +import java.util.LinkedList; import java.util.stream.Stream; import static helpers.TestHelper.getDefaultDisplayName; @@ -23,7 +21,6 @@ class ProxyInstantiatorTest { - private final MultiValuedMap, ConstructorParameters> constructorParameters = new ArrayListValuedHashMap<>(); @TestFactory Stream Should_Instantiate_Abstract_Interface_Or_Annotation_Classes() { @@ -35,7 +32,7 @@ Stream Should_Instantiate_Abstract_Interface_Or_Annotation_Classes( private Executable Should_Instantiate_Abstract_Interface_Or_Annotation_Classes(final Class classToInstantiate) { return () -> { // given - final ProxyInstantiator instantiator = new ProxyInstantiator(classToInstantiate, constructorParameters); + final ProxyInstantiator instantiator = new ProxyInstantiator(classToInstantiate, new LinkedList<>()); // when final Object result = instantiator.instantiate(); @@ -48,7 +45,7 @@ private Executable Should_Instantiate_Abstract_Interface_Or_Annotation_Classes(f @Test void Should_Create_Java_Proxy_Which_Returns_Expected_Values() { // given - final ProxyInstantiator instantiator = new ProxyInstantiator(Interface.class, constructorParameters); + final ProxyInstantiator instantiator = new ProxyInstantiator(Interface.class, new LinkedList<>()); // when final Object result = instantiator.instantiate(); @@ -70,7 +67,7 @@ private Executable Should_Create_Abstract_Class_Without_Default_Constructor(fina return () -> { // given - final ProxyInstantiator instantiator = new ProxyInstantiator(classToInstantiate, constructorParameters); + final ProxyInstantiator instantiator = new ProxyInstantiator(classToInstantiate, new LinkedList<>()); // when final Object result = instantiator.instantiate(); diff --git a/src/test/java/pl/pojo/tester/internal/instantiator/UserDefinedConstructorInstantiatorTest.java b/src/test/java/pl/pojo/tester/internal/instantiator/UserDefinedConstructorInstantiatorTest.java index 95dbbfa2..6d8fc830 100644 --- a/src/test/java/pl/pojo/tester/internal/instantiator/UserDefinedConstructorInstantiatorTest.java +++ b/src/test/java/pl/pojo/tester/internal/instantiator/UserDefinedConstructorInstantiatorTest.java @@ -2,8 +2,6 @@ import lombok.AllArgsConstructor; import lombok.Data; -import org.apache.commons.collections4.MultiValuedMap; -import org.apache.commons.collections4.multimap.ArrayListValuedHashMap; import org.junit.jupiter.api.DynamicTest; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.TestFactory; @@ -20,30 +18,13 @@ class UserDefinedConstructorInstantiatorTest { - private final MultiValuedMap, ConstructorParameters> constructorParameters = new ArrayListValuedHashMap<>(); - - { - constructorParameters.put(UserDefinedClass.class, - new ConstructorParameters(new Object[]{1, 2}, new Class[]{int.class, int.class})); - constructorParameters.put(ClassWithPrivateConstructor.class, - new ConstructorParameters(new Object[]{1}, new Class[]{int.class})); - constructorParameters.put(One_Arg_Constructor_Throws_NPE.class, - new ConstructorParameters(new Object[]{1}, new Class[]{Object.class})); - constructorParameters.put(No_Args_Constructor_Throws_NPE.class, - new ConstructorParameters(new Object[0], new Class[0])); - constructorParameters.put(InnerClass.class, - new ConstructorParameters(new Object[]{1}, new Class[]{int.class})); - constructorParameters.put(NestedClass.class, - new ConstructorParameters(new Object[]{1}, new Class[]{int.class})); - } - @Test void Should_Create_Object_Using_Private_Constructor() { // given final Class classToInstantiate = ClassWithPrivateConstructor.class; final UserDefinedConstructorInstantiator instantiator = new UserDefinedConstructorInstantiator( classToInstantiate, - constructorParameters); + new ConstructorParameters(new Object[]{ 1 }, new Class[]{ int.class })); // when final Object result = instantiator.instantiate(); @@ -58,7 +39,7 @@ void Should_Create_Object_For_Inner_Class() { final Class classToInstantiate = InnerClass.class; final UserDefinedConstructorInstantiator instantiator = new UserDefinedConstructorInstantiator( classToInstantiate, - constructorParameters); + new ConstructorParameters(new Object[]{ 1 }, new Class[]{ int.class })); // when final Object result = instantiator.instantiate(); @@ -73,7 +54,7 @@ void Should_Create_Object_For_Nested_Class() { final Class classToInstantiate = NestedClass.class; final UserDefinedConstructorInstantiator instantiator = new UserDefinedConstructorInstantiator( classToInstantiate, - constructorParameters); + new ConstructorParameters(new Object[]{ 1 }, new Class[]{ int.class })); // when final Object result = instantiator.instantiate(); @@ -95,7 +76,7 @@ private Executable Should_Throw_Exception_When_Cannot_Instantiate_Class(final Cl // given final UserDefinedConstructorInstantiator instantiator = new UserDefinedConstructorInstantiator( classToInstantiate, - constructorParameters); + new ConstructorParameters(new Object[0], new Class[0])); // when final Throwable result = catchThrowable(instantiator::instantiate); diff --git a/src/test/java/pl/pojo/tester/internal/tester/AbstractTesterTest.java b/src/test/java/pl/pojo/tester/internal/tester/AbstractTesterTest.java index 7a9cbc53..5b144bb3 100644 --- a/src/test/java/pl/pojo/tester/internal/tester/AbstractTesterTest.java +++ b/src/test/java/pl/pojo/tester/internal/tester/AbstractTesterTest.java @@ -4,17 +4,21 @@ import helpers.RecursivelyEqualArgumentMatcher; import helpers.StringPredicateArgumentMatcher; import lombok.Data; -import org.apache.commons.collections4.multimap.ArrayListValuedHashMap; import org.junit.jupiter.api.Test; import pl.pojo.tester.api.ClassAndFieldPredicatePair; import pl.pojo.tester.internal.field.AbstractFieldValueChanger; import pl.pojo.tester.internal.field.DefaultFieldValueChanger; import pl.pojo.tester.internal.instantiator.ObjectGenerator; +import java.util.LinkedList; import java.util.function.Predicate; import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.*; +import static org.mockito.Mockito.argThat; +import static org.mockito.Mockito.eq; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; class AbstractTesterTest { @@ -105,7 +109,7 @@ void Should_Create_New_Object_Generator_When_User_Defined_Class_And_Constructor( final ObjectGenerator beforeChange = abstractTester.objectGenerator; // when - abstractTester.setUserDefinedConstructors(new ArrayListValuedHashMap<>()); + abstractTester.setUserDefinedInstantiators(new LinkedList<>()); final ObjectGenerator afterChange = abstractTester.objectGenerator; diff --git a/src/test/java/pl/pojo/tester/internal/tester/ConstructorTesterTest.java b/src/test/java/pl/pojo/tester/internal/tester/ConstructorTesterTest.java index bc66d9b8..9fe6d452 100644 --- a/src/test/java/pl/pojo/tester/internal/tester/ConstructorTesterTest.java +++ b/src/test/java/pl/pojo/tester/internal/tester/ConstructorTesterTest.java @@ -1,10 +1,7 @@ package pl.pojo.tester.internal.tester; import classesForTest.ClassWithSyntheticConstructor; -import org.apache.commons.collections4.MultiValuedMap; -import org.apache.commons.collections4.multimap.ArrayListValuedHashMap; import org.junit.jupiter.api.Test; -import pl.pojo.tester.api.ConstructorParameters; import pl.pojo.tester.api.assertion.Assertions; import pl.pojo.tester.internal.assertion.constructor.ConstructorAssertionError; import pl.pojo.tester.internal.field.DefaultFieldValueChanger; @@ -19,9 +16,6 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.catchThrowable; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.spy; -import static org.mockito.Mockito.verify; class ConstructorTesterTest { @@ -76,67 +70,17 @@ void Should_Fail_Constructor_Tests() { } @Test - void Should_Use_User_Constructor_Parameters() { + void Should_Create_Constructor_Parameters() { // given final Class[] classesToTest = { ClassWithSyntheticConstructor.class }; - final ConstructorParameters parameters = new ConstructorParameters(new Object[]{ "string" }, - new Class[]{ String.class }); - final MultiValuedMap, ConstructorParameters> constructorParameters = spy(new ArrayListValuedHashMap<>()); - constructorParameters.put(ClassWithSyntheticConstructor.class, parameters); - - final ConstructorTester constructorTester = new ConstructorTester(); - constructorTester.setUserDefinedConstructors(constructorParameters); - - // when - final Throwable result = catchThrowable(() -> constructorTester.testAll(classesToTest)); - - // then - assertThat(result).isNull(); - verify(constructorParameters).get(ClassWithSyntheticConstructor.class); - } - - @Test - void Should_Create_Constructor_Parameters_When_Parameters_Are_Not_Provided() { - // given - final Class[] classesToTest = { ClassWithSyntheticConstructor.class }; - - final MultiValuedMap, ConstructorParameters> constructorParameters = spy(new ArrayListValuedHashMap<>()); - - final ConstructorTester constructorTester = new ConstructorTester(); - constructorTester.setUserDefinedConstructors(constructorParameters); - - // when - final Throwable result = catchThrowable(() -> constructorTester.testAll(classesToTest)); - - // then - assertThat(result).isNull(); - verify(constructorParameters, never()).get(ClassWithSyntheticConstructor.class); - } - - @Test - void Should_Create_Constructor_Parameters_When_Could_Not_Find_Matching_Constructor_Parameters_Types() { - // given - final Class[] classesToTest = { ClassWithSyntheticConstructor.class }; - - final ConstructorParameters parameters = spy(new ConstructorParameters(new Object[]{ "to", - "many", - "parameters" }, - new Class[]{ String.class, - String.class, - String.class })); - final MultiValuedMap, ConstructorParameters> constructorParameters = spy(new ArrayListValuedHashMap<>()); - constructorParameters.put(ClassWithSyntheticConstructor.class, parameters); - final ConstructorTester constructorTester = new ConstructorTester(); - constructorTester.setUserDefinedConstructors(constructorParameters); // when final Throwable result = catchThrowable(() -> constructorTester.testAll(classesToTest)); // then assertThat(result).isNull(); - verify(parameters, never()).getParameters(); } private static class Pojo {