Testing getter/setter using JUnit

Unit testing can be difficult. I give an example on how a property access test can fail.

So, I was thinking of testing my getter and setters in a JUnit test. Yea, I know it is not recommended, but I thought that I could write a simple reflective iterator that could do it without much fuss.

What I show below is that maybe getter/setters should be tested, especially in Java which really does not have “real” properties. Further, by investigating a potential solution, I show that naive testing will not work, and the reason is that testing IS hard to do.

Opponents of unit testing getter/setters are making a category error. They are equating the getter/setter idiom with the non-existent support for language level Properties in some languages, like Java.

A method named getFoo(), provides no guarantees on how it is getting the result, could be a field, could be a webservice, etc., and thus can fail like anything else.

 

Anyway, just to save time, and not have to code this, I did a quick search and found that this has been done many times before. So I looked at one of the solutions, Scott’s. Very nicely done! With one line you can test a class’s property getters and setters. Then I noticed a problem.

In his approach he invokes the setter and then the getter, finally comparing that the values are the same. For example, if the property is a boolean, the test class will set it true, then read it and the value better be true. However, what if the value prior to your set was true, the object is initialized with true for the field value?

For example, I took a class and set field x to true via the default constructor, then I modified the setX method to not set the field value.

public class Fubar {
  private boolean launch = true;
  
  public void getLaunch(){ 
      return this.launch;
  }

  public void setLaunch(boolean launch){  
      /* this.launch = launch; */ // broken!
  }
}

Code at: git clone git://gist.github.com/1408493.git gist-1408493

In the unit test the getLaunch method still returned true. The getter/setter test did not fail; the test was bogus. Not only that, the fact that the setLaunch method did not work illustrates that sometimes testing setters is warranted.

Thus, the version of the program that controls the sports strategy will ship and the boolean that aborts a play cannot be set to false! (Edited, removed joke about war stuff; you can’t be too careful with all the craziness in the world).

Updates
March 9 2014: I forked the original code with minor changes to a GitHub repository at: https://github.com/josefbetancourt/property-asserter.git
March 4, 2014: Just today a co-worker had an issue with a class. The getter was trying to return a value that was defined as transient. Thus, on deserialization the field was returning a null. The unit test could have provided a test for this. If a class implements Serializable, then it should include tests using serialization, and so forth.
March 2, 2014: I had a “heated” discussion with coworkers on this. I attempted to defend this post’s ideas. They asserted that this is a bogus example, and the issue is only applicable to boolean or primitives types. I contend that in fact it is very applicable where:

  • There are defaults of any kind.
  • There are methods that change object state. (Note: XUnit approach cannot test side effects unless they are part of the public interface)
  • The class will be maintained in the future.

That pretty much includes all non-trivial classes.

Feb 11, 2012: I’m using Scott’s solution in our test suite. I did modify the code a bit. Turns out that a JavaBean property is not so clear cut. If you have a getter and setter method pair but no actual target field, are those Javabean methods? Looks like the Java bean introspector will report these as bean accessors. Hmm.
June 7, 2013: There are two more issues with the above algorithm for testing getter/setters. First since the approach is for JavaBeans, there are issues with non-Javabeans.
    1. If the object doesn’t have a default constructor, one can’t automatically instantiate an object.
These are not insurmountable. The PropertyAsserter class has methods that take a class argument to use for testing a getter/setter.

 

In a recent presentation I gave on unit testing, I said that testing could be difficult. This is a great example of this. In this case, one should have followed analogous patterns in other fields. Thus, from semiconductor testing, for example, you would test gates by not just writing a 1 bit, you have to write 1 and 0 to make sure the gate is working, not stuck on high or low.

The bullet points

  1. Java Getter/Setters are a programmer’s agreement, easily broken.
  2. A getter/setter could be collaborating with external resources or services.
  3. A getter/setter could be part of a JavaBeans property event broadcasting requirement.
  4. If it can be automated, what’s the fuss?
  5. Never underestimated what could go wrong.
  6. Improves test coverage levels and get a pat on head from management.
  7. Would you not test a five cent metal washer on an interplanetary star ship?

Resources


Bill Evans Trio – Nardis – 19 Mar 65 (7 of 11)

Article on Bill Evans: http://www.chuckisraels.com/articleevans.htm

Leave a Reply

Your email address will not be published. Required fields are marked *