Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
195 changes: 195 additions & 0 deletions Bean.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,195 @@
package net.codebox.javabeantester.beans;

import java.lang.annotation.RetentionPolicy;
import java.util.Date;

/**
* Created by rob on 13/08/2017.
*/
public class Bean {
private String stringValue;
private Object[] arrayValue;
private boolean booleanValue;
private Boolean booleanWrapperValue;
private int intValue;
private Integer intWrapperValue;
private long longValue;
private Long longWrapperValue;
private double doubleValue;
private Double doubleWrapperValue;
private float floatValue;
private Float floatWrapperValue;
private char charValue;
private Character charWrapperValue;
private RetentionPolicy enumValue;
private Date noArgConstructorObjectValue;

private byte byteValue;
private Byte byteWrapperValue;
private List<Object> listValue;
private Set<Object> setValue;
private Map<Object,Object> mapValue;

public String getStringValue() {
return stringValue;
}

public void setStringValue(String stringValue) {
this.stringValue = stringValue;
}

public Object[] getArrayValue() {
return arrayValue;
}

public void setArrayValue(Object[] arrayValue) {
this.arrayValue = arrayValue;
}

public boolean isBooleanValue() {
return booleanValue;
}

public void setBooleanValue(boolean booleanValue) {
this.booleanValue = booleanValue;
}

public Boolean getBooleanWrapperValue() {
return booleanWrapperValue;
}

public void setBooleanWrapperValue(Boolean booleanWrapperValue) {
this.booleanWrapperValue = booleanWrapperValue;
}

public int getIntValue() {
return intValue;
}

public void setIntValue(int intValue) {
this.intValue = intValue;
}

public Integer getIntWrapperValue() {
return intWrapperValue;
}

public void setIntWrapperValue(Integer intWrapperValue) {
this.intWrapperValue = intWrapperValue;
}

public long getLongValue() {
return longValue;
}

public void setLongValue(long longValue) {
this.longValue = longValue;
}

public Long getLongWrapperValue() {
return longWrapperValue;
}

public void setLongWrapperValue(Long longWrapperValue) {
this.longWrapperValue = longWrapperValue;
}

public double getDoubleValue() {
return doubleValue;
}

public void setDoubleValue(double doubleValue) {
this.doubleValue = doubleValue;
}

public Double getDoubleWrapperValue() {
return doubleWrapperValue;
}

public void setDoubleWrapperValue(Double doubleWrapperValue) {
this.doubleWrapperValue = doubleWrapperValue;
}

public float getFloatValue() {
return floatValue;
}

public void setFloatValue(float floatValue) {
this.floatValue = floatValue;
}

public Float getFloatWrapperValue() {
return floatWrapperValue;
}

public void setFloatWrapperValue(Float floatWrapperValue) {
this.floatWrapperValue = floatWrapperValue;
}

public char getCharValue() {
return charValue;
}

public void setCharValue(char charValue) {
this.charValue = charValue;
}

public Character getCharWrapperValue() {
return charWrapperValue;
}

public void setCharWrapperValue(Character charWrapperValue) {
this.charWrapperValue = charWrapperValue;
}

public RetentionPolicy getEnumValue() {
return enumValue;
}

public void setEnumValue(RetentionPolicy enumValue) {
this.enumValue = enumValue;
}

public Date getNoArgConstructorObjectValue() {
return noArgConstructorObjectValue;
}

public void setNoArgConstructorObjectValue(Date noArgConstructorObjectValue) {
this.noArgConstructorObjectValue = noArgConstructorObjectValue;
}
public String getByteValue() {
return byteValue;
}

public void setByteValue(byte byteValue) {
this.byteValue = byteValue;
}
public String getByteWrapperValue() {
return byteWrapperValue;
}

public void setByteWrapperValue(byte byteWrapperValue) {
this.byteWrapperValue = byteWrapperValue;
}
public List<?> getListValue() {
return listValue;
}

public void setListValue(List<?> listValue) {
this.listValue = listValue;
}
public Set<?> getSetValue() {
return setValue;
}

public void setSetValue(Set<?> setValue) {
this.setValue = setValue;
}
public Map<?,?> getMapValue() {
return mapValue;
}

public void setMapValue(Map<?,?> mapValue) {
this.mapValue = mapValue;
}
}
158 changes: 158 additions & 0 deletions JavaBeanTester.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
package net.codebox.javabeantester;

import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import static org.junit.Assert.*;

/**
* This helper class can be used to unit test the get/set methods of JavaBean-style Value Objects.
*
* @author rob.dawson
*/
public class JavaBeanTester {
/**
* Tests the get/set methods of the specified class.
*
* @param <T> the type parameter associated with the class under test
* @param clazz the Class under test
* @param skipThese the names of any properties that should not be tested
* @throws IntrospectionException thrown if the Introspector.getBeanInfo() method throws this exception
* for the class under test
*/
public static <T> int test(final Class<T> clazz, final String... skipThese) throws IntrospectionException {
int methodsTested = 0;

final PropertyDescriptor[] props = Introspector.getBeanInfo(clazz).getPropertyDescriptors();
nextProp: for (PropertyDescriptor prop : props) {
// Check the list of properties that we don't want to test
for (String skipThis : skipThese) {
if (skipThis.equals(prop.getName())) {
continue nextProp;
}
}

final Method getter = prop.getReadMethod();
final Method setter = prop.getWriteMethod();

if (getter != null && setter != null){
// We have both a get and set method for this property
final Class<?> returnType = getter.getReturnType();
final Class<?>[] params = setter.getParameterTypes();

if (params.length == 1 && params[0] == returnType){
// The set method has 1 argument, which is of the same type as the return type of the get method, so we can test this property
try{
// Build a value of the correct type to be passed to the set method
Object value = buildValue(returnType);

// Build an instance of the bean that we are testing (each property test gets a new instance)
T bean = clazz.newInstance();

// Call the set method, then check the same value comes back out of the get method
setter.invoke(bean, value);

final Object expectedValue = value;
final Object actualValue = getter.invoke(bean);

assertEquals(String.format("Failed while testing property %s", prop.getName()), expectedValue, actualValue );

++methodsTested;

} catch (Exception ex){
fail(String.format("An exception was thrown while testing the property %s: %s", prop.getName(), ex.toString()));
}
}
}
}
return methodsTested;
}

private static Object buildMockValue(Class<?> clazz){
if (!Modifier.isFinal(clazz.getModifiers())){
// Insert a call to your favourite mocking framework here
return null;
} else {
return null;
}
}

private static Object buildValue(Class<?> clazz) throws InstantiationException, IllegalAccessException, IllegalArgumentException, SecurityException, InvocationTargetException{
// If we are using a Mocking framework try that first...
final Object mockedObject = buildMockValue(clazz);
if (mockedObject != null){
return mockedObject;
}

// Next check for a no-arg constructor
final Constructor<?>[] ctrs = clazz.getConstructors();
for (Constructor<?> ctr : ctrs) {
if (ctr.getParameterTypes().length == 0) {
// The class has a no-arg constructor, so just call it
return ctr.newInstance();
}
}

// Specific rules for common classes
if (clazz == String.class){
return "testvalue";

} else if (clazz.isArray()){
return Array.newInstance(clazz.getComponentType(), 1);

} else if (clazz == boolean.class || clazz == Boolean.class){
return true;

} else if (clazz == int.class || clazz == Integer.class) {
return 1;

} else if (clazz == long.class || clazz == Long.class) {
return 1L;

} else if (clazz == double.class || clazz == Double.class) {
return 1.0D;

} else if (clazz == float.class || clazz == Float.class) {
return 1.0F;

} else if (clazz == char.class || clazz == Character.class) {
return 'Y';

} else if (clazz == byte.class || clazz == Byte.class) {
return (byte) 1;
} else if (clazz == List.class) {
return new ArrayList<>();
} else if (clazz == Map.class) {
return new HashMap<>();
} else if (clazz == Set.class) {
return new HashSet<>();
} else if (clazz == Date.class) {
return new Date(0);

} else if (clazz.isEnum()) {
return clazz.getEnumConstants()[0];

// Add your own rules here

} else {
fail("Unable to build an instance of class " + clazz.getName() + ", please add some code to the "
+ JavaBeanTester.class.getName() + " class to do this.");
return null; // for the compiler
}
}

}