From 8626cb4ff1100083509992e2fc57dacd7ae09d05 Mon Sep 17 00:00:00 2001 From: "Ing. Luis Cardozo" Date: Fri, 19 Oct 2018 14:31:48 -0300 Subject: [PATCH 1/3] Creating a test-jar in order to use this project directly in another project. See https://maven.apache.org/plugins/maven-jar-plugin/examples/create-test-jar.html --- pom.xml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/pom.xml b/pom.xml index 935d459..236464e 100644 --- a/pom.xml +++ b/pom.xml @@ -25,6 +25,18 @@ 1.8 + + org.apache.maven.plugins + maven-jar-plugin + 3.1.0 + + + + test-jar + + + + From ef66e7c3e86281ccd8efccf1dd598a3efac314aa Mon Sep 17 00:00:00 2001 From: "Ing. Luis Cardozo" Date: Fri, 19 Oct 2018 16:23:46 -0300 Subject: [PATCH 2/3] Adding README.md --- README.md | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..f4087c8 --- /dev/null +++ b/README.md @@ -0,0 +1,34 @@ +DTO Tester, as explained in the Blog Post "[Automatically JUnit Test DTO and Transfer Objects](https://objectpartners.com/2016/02/16/automatically-junit-test-dto-and-transfer-objects/)" + + +To use it as a maven dependency, build it and install in your local maven repository using `mvn install` and import in your project as a test-scoped dependency. E.g.: + +``` + + com.objectpartners + dtotester + tests + test-jar + 0.0.1-SNAPSHOT + test + +``` + +To test simple DTOs, extend DtoTest<> in your test class: + +``` +package your.package; + +import com.objectpartners.DtoTest; + +public class MyOwnDtoTest extends DtoTest { + + @Override + protected MyOwnDto getInstance() { + return new MyOwnDto(); + } + +} +``` + +For more information, please read the [blog post](https://objectpartners.com/2016/02/16/automatically-junit-test-dto-and-transfer-objects/) \ No newline at end of file From a21c2db114c1acd15f3dfbf309b04c00902e34b8 Mon Sep 17 00:00:00 2001 From: "Ing. Luis Cardozo" Date: Wed, 19 Jun 2019 11:59:14 -0400 Subject: [PATCH 3/3] Changed the way of creating the jar file to the 'preferred way' according to https://maven.apache.org/plugins/maven-jar-plugin/examples/create-test-jar.html --- README.md | 7 +- pom.xml | 17 +- .../objectpartners/EverythingTransfer.java | 169 ----------- src/test/java/com/objectpartners/DtoTest.java | 270 ------------------ .../EverythingTransferTest.java | 13 - .../com/objectpartners/GetterSetterPair.java | 59 ---- 6 files changed, 5 insertions(+), 530 deletions(-) delete mode 100644 src/main/java/com/objectpartners/EverythingTransfer.java delete mode 100644 src/test/java/com/objectpartners/DtoTest.java delete mode 100644 src/test/java/com/objectpartners/EverythingTransferTest.java delete mode 100644 src/test/java/com/objectpartners/GetterSetterPair.java diff --git a/README.md b/README.md index f4087c8..080ebcc 100644 --- a/README.md +++ b/README.md @@ -7,9 +7,7 @@ To use it as a maven dependency, build it and install in your local maven reposi com.objectpartners dtotester - tests - test-jar - 0.0.1-SNAPSHOT + 0.0.2-SNAPSHOT test ``` @@ -31,4 +29,5 @@ public class MyOwnDtoTest extends DtoTest { } ``` -For more information, please read the [blog post](https://objectpartners.com/2016/02/16/automatically-junit-test-dto-and-transfer-objects/) \ No newline at end of file +For more information, please read the [blog post](https://objectpartners.com/2016/02/16/automatically-junit-test-dto-and-transfer-objects/) + diff --git a/pom.xml b/pom.xml index 236464e..b656ba8 100644 --- a/pom.xml +++ b/pom.xml @@ -4,11 +4,11 @@ com.objectpartners dtotester - 0.0.1-SNAPSHOT + 0.0.2-SNAPSHOT jar dtotester - http://maven.apache.org + https://objectpartners.com/2016/02/16/automatically-junit-test-dto-and-transfer-objects/ UTF-8 @@ -25,18 +25,6 @@ 1.8 - - org.apache.maven.plugins - maven-jar-plugin - 3.1.0 - - - - test-jar - - - - @@ -51,7 +39,6 @@ junit junit 4.11 - test diff --git a/src/main/java/com/objectpartners/EverythingTransfer.java b/src/main/java/com/objectpartners/EverythingTransfer.java deleted file mode 100644 index a83687e..0000000 --- a/src/main/java/com/objectpartners/EverythingTransfer.java +++ /dev/null @@ -1,169 +0,0 @@ -package com.objectpartners; - -import java.util.Date; - -/** - * An example object with all primitives to verify code coverage. - */ -public class EverythingTransfer { - - private Boolean booleanObject; - private Byte byteObject; - private Character characterObject; - private Date dateObject; - private Double doubleObject; - private Float floatObject; - private Integer intObject; - private Long longObject; - private Double noSetterDouble; - private boolean primitiveBoolean; - private byte primitiveByte; - private char primitiveCharacter; - private double primitiveDouble; - private float primitiveFloat; - private int primitiveInt; - private long primitiveLong; - private short primitiveShort; - private Short shortObject; - - public Boolean getBooleanObject() { - return booleanObject; - } - - public Byte getByteObject() { - return byteObject; - } - - public Character getCharacterObject() { - return characterObject; - } - - public Date getDateObject() { - return dateObject; - } - - public Double getDoubleObject() { - return doubleObject; - } - - public Float getFloatObject() { - return floatObject; - } - - public Integer getIntObject() { - return intObject; - } - - public Long getLongObject() { - return longObject; - } - - public Double getNoSetterDouble() { - return noSetterDouble; - } - - public byte getPrimitiveByte() { - return primitiveByte; - } - - public char getPrimitiveCharacter() { - return primitiveCharacter; - } - - public double getPrimitiveDouble() { - return primitiveDouble; - } - - public float getPrimitiveFloat() { - return primitiveFloat; - } - - public int getPrimitiveInt() { - return primitiveInt; - } - - public long getPrimitiveLong() { - return primitiveLong; - } - - public short getPrimitiveShort() { - return primitiveShort; - } - - public Short getShortObject() { - return shortObject; - } - - public boolean isPrimitiveBoolean() { - return primitiveBoolean; - } - - public void setBooleanObject(Boolean booleanObject) { - this.booleanObject = booleanObject; - } - - public void setByteObject(Byte byteObject) { - this.byteObject = byteObject; - } - - public void setCharacterObject(Character characterObject) { - this.characterObject = characterObject; - } - - public void setDateObject(Date dateObject) { - this.dateObject = dateObject; - } - - public void setDoubleObject(Double doubleObject) { - this.doubleObject = doubleObject; - } - - public void setFloatObject(Float floatObject) { - this.floatObject = floatObject; - } - - public void setIntObject(Integer intObject) { - this.intObject = intObject; - } - - public void setLongObject(Long longObject) { - this.longObject = longObject; - } - - public void setPrimitiveBoolean(boolean primitiveBoolean) { - this.primitiveBoolean = primitiveBoolean; - } - - public void setPrimitiveByte(byte primitiveByte) { - this.primitiveByte = primitiveByte; - } - - public void setPrimitiveCharacter(char primitiveCharacter) { - this.primitiveCharacter = primitiveCharacter; - } - - public void setPrimitiveDouble(double primitiveDouble) { - this.primitiveDouble = primitiveDouble; - } - - public void setPrimitiveFloat(float primitiveFloat) { - this.primitiveFloat = primitiveFloat; - } - - public void setPrimitiveInt(int primitiveInt) { - this.primitiveInt = primitiveInt; - } - - public void setPrimitiveLong(long primitiveLong) { - this.primitiveLong = primitiveLong; - } - - public void setPrimitiveShort(short primitiveShort) { - this.primitiveShort = primitiveShort; - } - - public void setShortObject(Short shortObject) { - this.shortObject = shortObject; - } - -} diff --git a/src/test/java/com/objectpartners/DtoTest.java b/src/test/java/com/objectpartners/DtoTest.java deleted file mode 100644 index 453db4f..0000000 --- a/src/test/java/com/objectpartners/DtoTest.java +++ /dev/null @@ -1,270 +0,0 @@ -package com.objectpartners; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertSame; - -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.math.BigDecimal; -import java.util.Collections; -import java.util.Date; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Map.Entry; -import java.util.Set; -import java.util.SortedMap; -import java.util.SortedSet; -import java.util.TreeMap; -import java.util.function.Supplier; - -import org.junit.Test; - -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.ImmutableMap.Builder; - -/** - * A utility class which allows for testing entity and transfer object classes. This is mainly for code coverage since - * these types of objects are normally nothing more than getters and setters. If any logic exists in the method, then - * the get method name should be sent in as an ignored field and a custom test function should be written. - * - * @param The object type to test. - */ -public abstract class DtoTest { - - /** A map of default mappers for common objects. */ - private static final ImmutableMap, Supplier> DEFAULT_MAPPERS; - - static { - final Builder, Supplier> mapperBuilder = ImmutableMap.builder(); - - /* Primitives */ - mapperBuilder.put(int.class, () -> 0); - mapperBuilder.put(double.class, () -> 0.0d); - mapperBuilder.put(float.class, () -> 0.0f); - mapperBuilder.put(long.class, () -> 0l); - mapperBuilder.put(boolean.class, () -> true); - mapperBuilder.put(short.class, () -> (short) 0); - mapperBuilder.put(byte.class, () -> (byte) 0); - mapperBuilder.put(char.class, () -> (char) 0); - - mapperBuilder.put(Integer.class, () -> Integer.valueOf(0)); - mapperBuilder.put(Double.class, () -> Double.valueOf(0.0)); - mapperBuilder.put(Float.class, () -> Float.valueOf(0.0f)); - mapperBuilder.put(Long.class, () -> Long.valueOf(0)); - mapperBuilder.put(Boolean.class, () -> Boolean.TRUE); - mapperBuilder.put(Short.class, () -> Short.valueOf((short) 0)); - mapperBuilder.put(Byte.class, () -> Byte.valueOf((byte) 0)); - mapperBuilder.put(Character.class, () -> Character.valueOf((char) 0)); - - mapperBuilder.put(BigDecimal.class, () -> BigDecimal.ONE); - mapperBuilder.put(Date.class, () -> new Date()); - - /* Collection Types. */ - mapperBuilder.put(Set.class, () -> Collections.emptySet()); - mapperBuilder.put(SortedSet.class, () -> Collections.emptySortedSet()); - mapperBuilder.put(List.class, () -> Collections.emptyList()); - mapperBuilder.put(Map.class, () -> Collections.emptyMap()); - mapperBuilder.put(SortedMap.class, () -> Collections.emptySortedMap()); - - DEFAULT_MAPPERS = mapperBuilder.build(); - } - - /** The get fields to ignore and not try to test. */ - private final Set ignoredGetFields; - - /** - * A custom mapper. Normally used when the test class has abstract objects. - */ - private final ImmutableMap, Supplier> mappers; - - /** - * Creates an instance of {@link DtoTest} with the default ignore fields. - */ - protected DtoTest() { - this(null, null); - } - - /** - * Creates an instance of {@link DtoTest} with ignore fields and additional custom mappers. - * - * @param customMappers Any custom mappers for a given class type. - * @param ignoreFields The getters which should be ignored (e.g., "getId" or "isActive"). - */ - protected DtoTest(Map, Supplier> customMappers, Set ignoreFields) { - this.ignoredGetFields = new HashSet<>(); - if (ignoreFields != null) { - this.ignoredGetFields.addAll(ignoreFields); - } - this.ignoredGetFields.add("getClass"); - - if (customMappers == null) { - this.mappers = DEFAULT_MAPPERS; - } else { - final Builder, Supplier> builder = ImmutableMap.builder(); - builder.putAll(customMappers); - builder.putAll(DEFAULT_MAPPERS); - this.mappers = builder.build(); - } - } - - /** - * Calls a getter and verifies the result is what is expected. - * - * @param fieldName The field name (used for error messages). - * @param getter The get {@link Method}. - * @param instance The test instance. - * @param expected The expected result. - * - * @throws IllegalAccessException if this Method object is enforcing Java language access control and the underlying - * method is inaccessible. - * @throws IllegalArgumentException if the method is an instance method and the specified object argument is not an - * instance of the class or interface declaring the underlying method (or of a subclass or implementor - * thereof); if the number of actual and formal parameters differ; if an unwrapping conversion for - * primitive arguments fails; or if, after possible unwrapping, a parameter value cannot be converted to - * the corresponding formal parameter type by a method invocation conversion. - * @throws InvocationTargetException if the underlying method throws an exception. - */ - private void callGetter(String fieldName, Method getter, T instance, Object expected) - throws IllegalAccessException, IllegalArgumentException, InvocationTargetException { - - final Object getResult = getter.invoke(instance); - - if (getter.getReturnType().isPrimitive()) { - /* Calling assetEquals() here due to autoboxing of primitive to object type. */ - assertEquals(fieldName + " is different", expected, getResult); - } else { - /* This is a normal object. The object passed in should be the exactly same object we get back. */ - assertSame(fieldName + " is different", expected, getResult); - } - } - - /** - * Creates an object for the given {@link Class}. - * - * @param fieldName The name of the field. - * @param clazz The {@link Class} type to create. - * - * @return A new instance for the given {@link Class}. - * - * @throws InstantiationException If this Class represents an abstract class, an interface, an array class, a - * primitive type, or void; or if the class has no nullary constructor; or if the instantiation fails - * for some other reason. - * @throws IllegalAccessException If the class or its nullary constructor is not accessible. - * - */ - private Object createObject(String fieldName, Class clazz) - throws InstantiationException, IllegalAccessException { - - try { - final Supplier supplier = this.mappers.get(clazz); - if (supplier != null) { - return supplier.get(); - } - - if (clazz.isEnum()) { - return clazz.getEnumConstants()[0]; - } - - return clazz.newInstance(); - } catch (IllegalAccessException | InstantiationException e) { - throw new RuntimeException("Unable to create objects for field '" + fieldName + "'.", e); - } - } - - /** - * Returns an instance to use to test the get and set methods. - * - * @return An instance to use to test the get and set methods. - */ - protected abstract T getInstance(); - - /** - * Tests all the getters and setters. Verifies that when a set method is called, that the get method returns the - * same thing. This will also use reflection to set the field if no setter exists (mainly used for user immutable - * entities but Hibernate normally populates). - * - * @throws Exception If an expected error occurs. - */ - @Test - public void testGettersAndSetters() throws Exception { - /* Sort items for consistent test runs. */ - final SortedMap getterSetterMapping = new TreeMap<>(); - - final T instance = getInstance(); - - for (final Method method : instance.getClass().getMethods()) { - final String methodName = method.getName(); - - if (this.ignoredGetFields.contains(methodName)) { - continue; - } - - String objectName; - if (methodName.startsWith("get") && method.getParameters().length == 0) { - /* Found the get method. */ - objectName = methodName.substring("get".length()); - - GetterSetterPair getterSettingPair = getterSetterMapping.get(objectName); - if (getterSettingPair == null) { - getterSettingPair = new GetterSetterPair(); - getterSetterMapping.put(objectName, getterSettingPair); - } - getterSettingPair.setGetter(method); - } else if (methodName.startsWith("set") && method.getParameters().length == 1) { - /* Found the set method. */ - objectName = methodName.substring("set".length()); - - GetterSetterPair getterSettingPair = getterSetterMapping.get(objectName); - if (getterSettingPair == null) { - getterSettingPair = new GetterSetterPair(); - getterSetterMapping.put(objectName, getterSettingPair); - } - getterSettingPair.setSetter(method); - } else if (methodName.startsWith("is") && method.getParameters().length == 0) { - /* Found the is method, which really is a get method. */ - objectName = methodName.substring("is".length()); - - GetterSetterPair getterSettingPair = getterSetterMapping.get(objectName); - if (getterSettingPair == null) { - getterSettingPair = new GetterSetterPair(); - getterSetterMapping.put(objectName, getterSettingPair); - } - getterSettingPair.setGetter(method); - } - } - - /* - * Found all our mappings. Now call the getter and setter or set the field via reflection and call the getting - * it doesn't have a setter. - */ - for (final Entry entry : getterSetterMapping.entrySet()) { - final GetterSetterPair pair = entry.getValue(); - - final String objectName = entry.getKey(); - final String fieldName = objectName.substring(0, 1).toLowerCase() + objectName.substring(1); - - if (pair.hasGetterAndSetter()) { - /* Create an object. */ - final Class parameterType = pair.getSetter().getParameterTypes()[0]; - final Object newObject = createObject(fieldName, parameterType); - - pair.getSetter().invoke(instance, newObject); - - callGetter(fieldName, pair.getGetter(), instance, newObject); - } else if (pair.getGetter() != null) { - /* - * Object is immutable (no setter but Hibernate or something else sets it via reflection). Use - * reflection to set object and verify that same object is returned when calling the getter. - */ - final Object newObject = createObject(fieldName, pair.getGetter().getReturnType()); - final Field field = instance.getClass().getDeclaredField(fieldName); - field.setAccessible(true); - field.set(instance, newObject); - - callGetter(fieldName, pair.getGetter(), instance, newObject); - } - } - } -} diff --git a/src/test/java/com/objectpartners/EverythingTransferTest.java b/src/test/java/com/objectpartners/EverythingTransferTest.java deleted file mode 100644 index c9dbf7d..0000000 --- a/src/test/java/com/objectpartners/EverythingTransferTest.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.objectpartners; - -/** - * Tests the {@link EverythingTransfer} class. - */ -public class EverythingTransferTest extends DtoTest { - - @Override - protected EverythingTransfer getInstance() { - return new EverythingTransfer(); - } - -} diff --git a/src/test/java/com/objectpartners/GetterSetterPair.java b/src/test/java/com/objectpartners/GetterSetterPair.java deleted file mode 100644 index 9814915..0000000 --- a/src/test/java/com/objectpartners/GetterSetterPair.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.objectpartners; - -import java.lang.reflect.Method; - -/** - * A utility class which holds a related getter and setter method. - */ -public class GetterSetterPair { - /** The get method. */ - private Method getter; - - /** The set method. */ - private Method setter; - - /** - * Returns the get method. - * - * @return The get method. - */ - public Method getGetter() { - return getter; - } - - /** - * Returns the set method. - * - * @return The set method. - */ - public Method getSetter() { - return setter; - } - - /** - * Returns if this has a getter and setting method set. - * - * @return If this has a getter and setting method set. - */ - public boolean hasGetterAndSetter() { - return this.getter != null && this.setter != null; - } - - /** - * Sets the get Method. - * - * @param getter The get Method. - */ - public void setGetter(Method getter) { - this.getter = getter; - } - - /** - * Sets the set Method. - * - * @param setter The set Method. - */ - public void setSetter(Method setter) { - this.setter = setter; - } -}