43

There is a well-known debate in Java (and other communities, I'm sure) whether or not trivial getter/setter methods should be tested. Usually, this is with respect to code coverage. Let's agree that this is an open debate, and not try to answer it here.

There have been several blog posts on using Java reflection to auto-test such methods.

Does any framework (e.g. jUnit) provide such a feature? e.g. An annotation that says "this test T should auto-test all the getters/setters on class C, because I assert that they are standard".

It seems to me that it would add value, and if it were configurable, the 'debate' would be left as an option to the user.

Jason Etheridge
  • 6,849
  • 5
  • 30
  • 33
Michael Easter
  • 23,733
  • 7
  • 76
  • 107
  • 1
    Yes. See `nl.jqno.equalsverifier.EqualsVerifier` and https://www.javacodegeeks.com/2014/09/tips-for-unit-testing-javabeans.html – Barett Nov 15 '16 at 18:19
  • See https://www.pojo.pl/comparison/ (may be outdated though since the GitHub page says the project is not maintained anymore). – Leponzo Sep 21 '21 at 20:24

10 Answers10

17

I created the OpenPojo project for solving this exact problem.

The project allows you to validate:

  • Enforce Pojo coding standard (i.e. All fields private, or no native variables, ...etc)
  • Enforce Pojo behaviour (i.e. setter does JUST setting, no transformation, etc)
  • Validate Pojo Identity (i.e. Use annotation based equality & hashcode generation)

See Tutorial

Ruslan López
  • 4,433
  • 2
  • 26
  • 37
Osman Shoukry
  • 294
  • 2
  • 6
  • 2
    My qualm is with the name: that you aren't testing POJOs you are actually testing Java Beans. [_"The term "POJO" is mainly used to denote a Java object which does not follow any of the major Java object models, conventions, or frameworks."_](http://en.wikipedia.org/wiki/Plain_Old_Java_Object) the getter/setter is a convention. [_"Java Beans are serializable, have a 0-argument constructor, and allow access to properties using getter and setter methods."_](http://en.wikipedia.org/wiki/Java_Beans). – Sled Mar 21 '14 at 16:24
  • Note: you have to use it in your code for generating hashcode, equals and toString – Ruslan López Aug 11 '18 at 17:48
  • 1
    @ArtB - The wiki entry you link to defines a JavaBean as a type of POJO: "A JavaBean is a POJO that is serializable, has a no-argument constructor, and allows access to properties using getter and setter methods that follow a simple naming convention." – Jonathan Sterling Sep 27 '18 at 04:53
  • @JonathanSterling "POJO" was just a term [invented to give a sexy name](https://www.martinfowler.com/bliki/POJO.html) to classes that weren't limited by some framework, library, or convention. So to have a library for testing the specific conventions around beans named after "POJO" (which IMHO is best translated as "free form") isn't the best use of nomenclature... but I have used and [recommended the library before](https://stackoverflow.com/a/6206564/254477). – Sled Sep 27 '18 at 13:44
14

I'm not aware of any readily available library or class that does this. This may mainly be because I don't care as I am on the side of strongly opposing such tests. So even though you asked there must be a bit of justification for this view:

I doubt that autotesting getters and setters benefit your code quality or your coverage: Either these methods are used from other code (and tested there, e.g. 100% covered) or not used at all (and could be removed). In the end you'll leave getters and setters in because they are used from the test but nowhere else in the application.

It should be easy to write such a test, e.g. with Apache Commons BeanUtils, but I doubt you really need it if you have good tests otherwise.

Olaf Kock
  • 46,930
  • 8
  • 59
  • 90
  • 1
    We once had to implement tests like that because the getters and setters were only used in a dependent project and as such not touched in the unit tests of their own project. – jan.vdbergh Sep 20 '08 at 17:17
  • 1
    Late comment - sorry: This would most likely be for code coverage reasons. You might need to do that for these reasons, but I doubt you'll get quality tests from it. I can easily write crappy tests that provide 100% coverage without any benefit at all. Was that why you "had to"? – Olaf Kock Dec 11 '08 at 16:41
  • I do see value, although limited. People often copy/paste getters and setters. When they do, they sometimes forget to do one of the edits, A simple generated test could catch that. – kc2001 Jul 22 '19 at 00:27
9

Unitils does this w/ the static method assertRefEquals.

Kevin Wong
  • 14,656
  • 11
  • 42
  • 52
7

In the most cases setter and getter do more as only setting and getting an internal field. An Object has to check internal rules that it hold only valid values. For example

  • are null values possible?
  • are empty strings possible?
  • or negative values?
  • or a zero value?
  • or values from a list are valid?
  • or is there a maximal value?
  • or is there a maximum precision on BigDecimal values?

The unit test should check if the behavior correct if there invalid values. This can not be automated.

If you have no logic on the setter and getter then it must be used anywhere in your application. Write a test where your object is a parameter for a more complex test. You can test it then with different values from the list.

Test your business logic and not the getter and setter. The result should also a coverage of the getter and setter. The methods should be any result in your business logic also if you have only a public library. If the getter and setter have no code coverage then removed it.

Horcrux7
  • 23,758
  • 21
  • 98
  • 156
5

I've done something like that. A simple java class that takes an object and test all the getters and setter methods. http://sourceforge.net/projects/getterandsetter/

I do think you should avoid getter and setter methods as much as possible, but as long as they're around and it takes two lines to test them, it's a good thing to do it.

3

I'll favor OO design over code coverage, and see if I cannot move those fields to the class that needs them. So I would try to see if those getters and setters can be removed, as suggested before. getters and setters are breaking encapsulation.

Sam Holder
  • 32,535
  • 13
  • 101
  • 181
philant
  • 34,748
  • 11
  • 69
  • 112
2

I am trying out openpojo

I have kicked the tires and it seems to do the job.

  1. It allows you to check all the pojo's in your project.
  2. It seems to check the best practices on pojo's

Check this tutorial for a quick start Tutorial

NoNaMe
  • 6,020
  • 30
  • 82
  • 110
maasha
  • 21
  • 1
  • I have a problem with openpojo. For classes that "extends" a base class, openpojo looks for "declared" fields. Eg: abstract base class has 4 fields and concrete derived classes has 2 extra fields, only 2 fields will be tested. – Titi Wangsa bin Damhore Sep 27 '14 at 14:10
  • @TitiWangsabinDamhore I don't see the problem, if they are setters & getters then there is no other interaction then they will be tested as part of the parent/base class. The only situation I can imagine it mattering is if the field was protected, and the sub-class had stricter validation occurring in the setter than the parent class. – Sled Sep 07 '16 at 14:26
  • @ArtB the problem occurs when the base class is abstract. Eg. AbstractHouse has 2 fields, 2 setter methods and 2 getter methods. There is sub class. ExpensiveHouse extends AbstractHouse it has 1 extra field, 1 getter and 1 setter. When I test ExpensiveHouse, open pojo looks at the declared field and executes 1 setter method and 1 getter method. Cobertura reports that AbstractHouse was not tested. Anwyay, this was my problem in 2014, not sure if OpenPojo still behaves this way. If I do test(new AbstractHouse(){}); this the declared fields are nothing and no setters or getters are executed. – Titi Wangsa bin Damhore Sep 09 '16 at 05:16
1

I guess this library is the answer to your question

it tests all the bean's initial values, the setters, the getters, hashCode(), equals() and toString(). All you have to do is define a map of default and non default property/value.

It can also test objects that are beans with additional non default constructors.

Franck Valentin
  • 1,115
  • 8
  • 14
0

Answering the previous comment at @me here because of my reputation:

Vlookward, not writing getters/setters makes no sense at all. The only options for setting private fields is to have explicit setters, to set them in your constructor, or to set the indirectly via other methods (functionally deferring the setter to another place). Why not use setters?

Well, sometimes, there is no need to the field be private (Sorry if my English is not very good). Often, we write our software as it was a library and we encapsulate our fields (our business logic fields) with unnecessary getters/setters.

Other times, that methods are actually necessary. Then, there are two possibilities:
1. There is business logic inside them. Then they sould be tested, but they aren't real getters/setters. I always write that logic in other classes. And the tests test that other classes, not the POJO.
2. There is not. Then, do not write them by hand, if you can. For example, an implementation for the next interface may be fully autogenerated (and also in runtime!) :

interface NamedAndObservable {
  String getName();
  void setName(String name);
  void addPropertyChangeListener(PropertyChangeListener listener);
  void addPropertyChangeListener(String propertyName,
                                 PropertyChangeListener listener);
}

So test only what is written by hand. No matter if it is a getter/setter.

Community
  • 1
  • 1
Daniel Fanjul
  • 3,493
  • 3
  • 26
  • 29
0

I don't write test cases for each property, but instead test all of the setters/getters in a single test case using reflection/introspector to determine the type(s). Here is a great resource that shows this:

http://www.nearinfinity.com/blogs/scott_leberknight/do_you_unit_test_getters.html

Carol Skelly
  • 351,302
  • 90
  • 710
  • 624