Monday, February 09, 2009

JUnit auto SetGet

Using reflection and generics in Java, you can now automatically test Getters and Setters (accessors and mutators) of your class with JUnit/TestNG.

Of course normally many developers do not bother testing setters and getters, but if your customer insists on high test coverage you will find this auto one is useful to avoid boilerplate code :-) .
And maybe it can help to avoid some nasty bugs (I myself feel ashamed when reading my "sleepy" code, too) !


Some fragments :

public void invokeSettersAndGetters() {
Classextends Object> targetClass = testTarget.getClass();
Method[] methods = targetClass.getMethods();
for (int i = 0; i < methods.length; i++) { Method method = methods[i]; if (method.getName().startsWith("set")) { Class[] parameterTypes = method.getParameterTypes(); if (parameterTypes.length == 1) { Object testValue = testValueFactory.createValue(parameterTypes[0]); try { method.invoke(testTarget, testValue); if (testValue instanceof Boolean) { invokeGetter(targetClass, testValue, "is" + method.getName().substring(3)); } else { invokeGetter(targetClass, testValue, "get" + method.getName().substring(3)); } } catch (IllegalAccessException e) { Assert.fail("failed to access setter method: " + method.toString() + " - " + e.getMessage()); } catch (InvocationTargetException e) { Assert.fail("failed to invoke setter method: " + method.toString() + " - " + e.getMessage()); } } } } }





private void invokeGetter(Class targetClass, Object expectedValue, String getterName) {
try {
Method getterMethod = targetClass.getMethod(getterName);
if (log.isDebugEnabled()) {
log.debug("invoke get method: " + getterMethod.toString());
}
Object retrievedValue = getterMethod.invoke(testTarget);
Class returnType = getterMethod.getReturnType();
if (returnType.isPrimitive()) {
Assert.assertEquals("return value of " + getterName + " incorrect", expectedValue, retrievedValue);
} else {
Assert.assertSame("return value of " + getterName + " incorrect", expectedValue, retrievedValue);
}
} catch (NoSuchMethodException ignore) {
// ignore if getter does not exist
if (log.isDebugEnabled()) {
log.debug("getter does not exist: " + getterName);
}
} catch (IllegalAccessException e) {
Assert.fail("failed to access getter method: " + getterName + " - " + e.getMessage());
} catch (InvocationTargetException e) {
Assert.fail("failed to invoke getter method: " + getterName + " - " + e.getMessage());
}
}



basic JUnit test:

@Test
public void testSetterGetter() {
Cat cat = new Cat();
MutatorAccessorInvoker invoker = new MutatorAccessorInvoker(cat);
invoker.invokeSettersAndGetters();
}


Full credit of this invoker should belong to Koert Zeilstra , however you should see that his class can be improved ;-) .

@Test
public void setAndGetAll() {
MutatorAccessorInvoker mutatorAccessorInvoker = new MutatorAccessorInvoker(new MyGuess());
mutatorAccessorInvoker.invokeSettersAndGetters();
}




Have fun,

No comments: