Tuesday, May 27, 2008
Should We Test Getters and Setters?
byWhen new engineers are being brought into the fold of unit testing, one question invariably arises: “Should we test getters and setters?” The answer, in the humble opinion of this engineer, is yes. This is by no means a new argument; it has been raging across the software development field for years. Let’s face it, public getter and setter methods are (normally) inherently simple, and writing unit tests for them seem to be a waste of time – testing the language’s ability to set and pass variables instead of any actual code. But there are a few dangers lurking in not testing them…
Whenever I advocate testing getters and setters, the first argument I almost always get is, “A simple getter and setter can’t break.” Wrong. They can break, and I have seen it happen.
private int myValue;
…
public void setMyValue(int myvalue) {
this.myvalue = myvalue;
}
This implementation of a simple setter compiles just fine, yet when you run the code, myValue never gets set. Can you see why? In the setter method, there is a simple capitalization error. Now I realize that the compiler will throw a warning on this method, but as long as the code compiles, these warnings sometimes get ignored. I also realize that any good IDE worth its weight in Tab and Mountain Dew will auto generate getter and setters for you. Whether that is good or bad is up for debate (Allen Holub maintains that getters and setters are evil, therefore would really NOT want them auto generated), but either way this particular problem is eliminated.
This, however, is not the only way getters and setters can break. The easiest way that I know of to break code is by changing existing code without understanding the full ramifications of doing so. Testing getters and setters also guards against regression bugs. Here is an example of a simple getter
private Collection
...
public Collection
return myCollection;
}
This is a completely legitimate bean, and is working perfectly for Developer A. Because it was a “simple” getter, Developer A decided not to unit test it. Enter Developer B, who needs to use the method as well, but makes a slight change to guard against NullPointerExceptions.
private Collection
…
public Collection
if (myCollection == null)
myCollection = new ArrayList
return myCollection;
}
Developer B looks, and sees that there is not a unit test for the getter, and so decides to make one, adding in the edge case of the collection not being initialized and expecting an empty collection. No problem right?
Well, not for Developer B. But what if Developer A’s code relied on getting back a null value if the collection had not been initialized? His or her code, even though it still compiles, is no longer functioning as expected. We can hope, for Developer A’s sake, that he or she was testing the getter indirectly in a different unit test, and would be able to catch the regression bug. But I don’t like pinning my confidence in software quality to hope.
It only takes seconds to write unit tests for simple getters and setters. Most IDEs even generate the unit test stubs for you, so you only have to write a line or two per test. Given the incredibly low amount of time it takes to write the tests, is there really any good reason not to write them?
Again, in the humble opinion of this engineer, no.