Skip to content

Commit cfe7cce

Browse files
committed
Initial
0 parents  commit cfe7cce

File tree

2 files changed

+127
-0
lines changed

2 files changed

+127
-0
lines changed

JavaBeanTester.java

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
import java.beans.IntrospectionException;
2+
import java.beans.Introspector;
3+
import java.beans.PropertyDescriptor;
4+
import java.lang.reflect.Array;
5+
import java.lang.reflect.Constructor;
6+
import java.lang.reflect.InvocationTargetException;
7+
import java.lang.reflect.Method;
8+
import java.lang.reflect.Modifier;
9+
import static org.junit.Assert.*;
10+
11+
/**
12+
* This helper class can be used to unit test the get/set methods of JavaBean-style Value Objects.
13+
*
14+
* @author rob.dawson
15+
*/
16+
public class JavaBeanTester {
17+
/**
18+
* Tests the get/set methods of the specified class.
19+
*
20+
* @param <T> the type parameter associated with the class under test
21+
* @param clazz the Class under test
22+
* @param skipThese the names of any properties that should not be tested
23+
* @throws IntrospectionException thrown if the Introspector.getBeanInfo() method throws this exception
24+
* for the class under test
25+
*/
26+
public static <T> void test(final Class<T> clazz, final String... skipThese) throws IntrospectionException {
27+
final PropertyDescriptor[] props = Introspector.getBeanInfo(clazz).getPropertyDescriptors();
28+
nextProp: for (PropertyDescriptor prop : props) {
29+
// Check the list of properties that we don't want to test
30+
for (String skipThis : skipThese) {
31+
if (skipThis.equals(prop.getName())) {
32+
continue nextProp;
33+
}
34+
}
35+
final Method getter = prop.getReadMethod();
36+
final Method setter = prop.getWriteMethod();
37+
38+
if (getter != null && setter != null){
39+
// We have both a get and set method for this property
40+
final Class<?> returnType = getter.getReturnType();
41+
final Class<?>[] params = setter.getParameterTypes();
42+
43+
if (params.length == 1 && params[0] == returnType){
44+
// 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
45+
try{
46+
// Build a value of the correct type to be passed to the set method
47+
Object value = buildValue(returnType);
48+
49+
// Build an instance of the bean that we are testing (each property test gets a new instance)
50+
T bean = clazz.newInstance();
51+
52+
// Call the set method, then check the same value comes back out of the get method
53+
setter.invoke(bean, value);
54+
55+
final Object expectedValue = value;
56+
final Object actualValue = getter.invoke(bean);
57+
58+
assertEquals(String.format("Failed while testing property %s", prop.getName()), expectedValue, actualValue );
59+
60+
} catch (Exception ex){
61+
fail(String.format("An exception was thrown while testing the property %s: %s", prop.getName(), ex.toString()));
62+
}
63+
}
64+
}
65+
}
66+
}
67+
68+
private static Object buildMockValue(Class<?> clazz){
69+
if (!Modifier.isFinal(clazz.getModifiers())){
70+
// Insert a call to your favourite mocking framework here
71+
return null;
72+
} else {
73+
return null;
74+
}
75+
}
76+
77+
private static Object buildValue(Class<?> clazz) throws InstantiationException, IllegalAccessException, IllegalArgumentException, SecurityException, InvocationTargetException{
78+
// If we are using a Mocking framework try that first...
79+
final Object mockedObject = buildMockValue(clazz);
80+
if (mockedObject != null){
81+
return mockedObject;
82+
}
83+
84+
// Next check for a no-arg constructor
85+
final Constructor<?>[] ctrs = clazz.getConstructors();
86+
for (Constructor<?> ctr : ctrs) {
87+
if (ctr.getParameterTypes().length == 0) {
88+
// The class has a no-arg constructor, so just call it
89+
return ctr.newInstance();
90+
}
91+
}
92+
93+
// Specific rules for common classes
94+
if (clazz == String.class){
95+
return "testvalue";
96+
97+
} else if (clazz.isArray()){
98+
return Array.newInstance(clazz.getComponentType(), 1);
99+
100+
} else if (clazz == boolean.class || clazz == Boolean.class){
101+
return true;
102+
103+
} else if (clazz == int.class || clazz == Integer.class) {
104+
return 1;
105+
106+
} else if (clazz == long.class || clazz == Long.class) {
107+
return 1L;
108+
109+
} else if (clazz == double.class || clazz == Double.class) {
110+
return 1.0D;
111+
112+
} else if (clazz == float.class || clazz == Float.class) {
113+
return 1.0F;
114+
115+
} else if (clazz == char.class || clazz == Character.class) {
116+
return 'Y';
117+
118+
// Add your own rules here
119+
120+
} else {
121+
fail("Unable to build an instance of class " + clazz.getName() + ", please add some code to the "
122+
+ JavaBeanTester.class.getName() + " class to do this.");
123+
return null; // for the compiler
124+
}
125+
}
126+
}
127+

README

Whitespace-only changes.

0 commit comments

Comments
 (0)