Wednesday, March 12, 2008

Interesting unit tests in EJB code are hard to find

You write Java. You are using your wonderful coverage tools like EMMA to make sure your unit tests are great. You know what you can spend a lot of time keeping track of? Methods like this.

public int getFoo()
{
return foo;
}

public void setFoo(int foo)
{
this.foo = foo;
}

So f-in what? You write tests that check code that Eclipse will generate a warning for. I guess this is just a statement that coverage isn't everything. And I am not the first. But I would go further, and say that coverage is really, really misleading. Particularly when you are writing server-side Java code.

Not so obvious, but still meaningless, unit testing

EJB code is notoriously hard to test. Even these days, in the era of automatic object mocking. Take a look at the kind of bean code I see a lot of these days.

public void addFooToBar(long barId, Foo foo) throws SomeStuff
{
// em is an EntityManager instance
Bar bar = (Bar)em.createQuery("from Bar where id=:barId and other='constraint'")
.setParameter("barId", barId)
.getSingleResult();

bar.addFoo(foo);

em.merge(bar);
}

Initially, I was like, wow, with stuff like EasyMock I can actually get this covered! But then you realize that all interaction with the EntityManager is meaningless when you mock things out. What, are you going to do a string comparison that the query will work? Are you really interested in the call to .addFoo?

This kind of code is just as meaningless in a Java-based unit test as the standard bean property accessors. The reason of course is that all the real logic is in the string data — the database query — and interaction with the database.

Two interesting problems about uninteresting code

First, I want a way to measure interesting code. Number of statements? No, not really. If you could figure out anything that really interacts with certain interfaces and classes, like the EntityManager, well, maybe that might be interesting.

Second, I want a different framework that acts like a unit test for database interaction, both with toolkits like Hibernate, as well as straight JDBC. This, I think I could come up with. But I wouldn't use a Java-based unit test framework. That tests Java code, and here, I want to test database interaction. Different problems, and how well you write a DB test depends upon how far you push your schema, not on how many lines of Java code got executed. So the second problem is, with a DB-oriented test framework, how do you measure your schema variations?

No comments: