Pojo Properties Auto Testing

Doing another run of my TDD course, and one of the attendees raised an interesting question: are there any tools to automatically test pojo getters and setters? We couldn’t find any, and it sounded like a challenge worth tackling.

Now I don’t want to get into the debate about whether we should even bother to test simple getters and setters; the context here is that not doing so drags down the code coverage figures, putting the development team on the back foot when trying to justifying their code quality to “management”. So if something could automatically test the simple getters and setters, that would be a big win.

So, here, for your delectation, is my pojo property auto tester. It’s provided as a superclass testcase:

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

import org.junit.Assert;
import org.junit.Before;

public abstract class AbstractPojoTester {

	private Map testValues = new HashMap();

	protected void addTestValue(Class propertyType, Object testValue) {
		testValues.put(propertyType, testValue);
	}

	@Before
	public void setUpTestValues() throws Exception {
		// add in further test values here.
		addTestValue(String.class, "foo");
		addTestValue(int.class, 123);
		addTestValue(Integer.class, 123);
		addTestValue(double.class, 123.0);
		addTestValue(Double.class, 123.0);
		addTestValue(boolean.class, true);
		addTestValue(Boolean.class, true);
		addTestValue(java.util.Date.class, new java.util.Date(100, 3, 4, 11, 45));
	}

	/**
	 * Call from subclass
	 */
	protected void testPojo(Class pojoClass) {
		try {
			Object pojo = pojoClass.newInstance();
			BeanInfo pojoInfo = Introspector.getBeanInfo(pojoClass);
			for (PropertyDescriptor propertyDescriptor : pojoInfo
					.getPropertyDescriptors()) {
				testProperty(pojo, propertyDescriptor);
			}
		} catch (Exception e) {
			// ignore
		}
	}

	private void testProperty(Object pojo, PropertyDescriptor propertyDescriptor) {
		try {
			Class propertyType = propertyDescriptor.getPropertyType();
			Object testValue = testValues.get(propertyType);
			if (testValue == null) {
				return;
			}
			Method writeMethod = propertyDescriptor.getWriteMethod();
			Method readMethod = propertyDescriptor.getReadMethod();
			if (readMethod != null && writeMethod != null) {
				writeMethod.invoke(pojo, testValue);
				Assert.assertEquals(readMethod.invoke(pojo), testValue);
			}
 		} catch (Exception e) {
			// ignore
		}
	}
}

So, supposing you want to test this trivial pojo:

public class Person {
	private String name;
	private int age;
	private double salary;

	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}
	public int getAge() {
		return age;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public double getSalary() {
		return salary;
	}
	public void setSalary(double salary) {
		this.salary = salary;
	}
}

The test case for this is simply:

import org.junit.Test;

public class PersonTester extends AbstractPojoTester {
	@Test
	public void testGettersAndSetters() {
		testPojo(Person.class);
	}
}

Feel free to enhance as required…

Advertisement

Posted on June 11, 2010, in random. Bookmark the permalink. 5 Comments.

  1. What’s the point? Why add more testing boilerplate to test inconsequential methods? If the bean (btw, it’s a bean, not “pojo”) is indeed a “dto”-like class, why test it? And should you really want a compliance test (method signature / existence), which is sometimes needed to assure backwards compatibility / adherence to pre-set APIs, then the automatic approach wouldn’t work as well.

    I fail to see the point of such a test – when would it fail and what can you learn from such a failure?

    • The point, Ran, is, does your Dilbert boss also understand the difference? Or wouldn’t it be easier to placate them and then know that any code coverage score less than 100% is due to untested complex methods, rather than untested simple methods.
      Also, in terms of boilerplate, it’d be easy to write a JUnit4 test runner that would just iterate through all pojos on the classpath (perhaps it might require that they are annotated @Entity or @DTO). So there wouldn’t necessarily be any boilerplate at all to maintain. One could also annotate methods that just happen to be getXxx/setXxx but which don’t behave as “simple” data containers (eg they have extra behaviour) so that they get skipped by such a test runner, eg @NonProperty. Such an annotation would be useful for the developer as well when reading the pojo.

  2. How does this work with respect to generics? If my JavaBean or POJO has a List and List property, how does the testValues map deal with those, because it appears to be broken in that respect!

    • Hi David,
      No, you’re right – this simple class doesn’t deal with lists. It was just something I put together in a lunch break while teaching my TDD course. You’re welcome to enhance for your own needs.
      Cheers
      Dan

  1. Pingback: Resumen semanal de pequeños trucos de Java. « Jbravomontero's Blog

Leave a Reply

Fill in your details below or click an icon to log in:

Gravatar
WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 109 other followers