Should unit tests be written for getter and setters?

I would say no.

@Will said you should aim for 100% code coverage, but in my opinion that's a dangerous distraction. You can write unit tests that have 100% coverage, and yet test absolutely nothing.

Unit tests are there to test the behaviour of your code, in an expressive and meaningful way, and getters/setters are only a means to an end. If you tests use the getters/setters to achieve their goal of testing the "real" functionality, then that's good enough.

If, on the other hand, your getters and setters do more than just get and set (i.e. they're properly complex methods), then yes, they should be tested. But don't write a unit test case just to test a getter or setters, that's a waste of time.


A resounding YES with TDD


Note: This answer keeps getting upvotes, albeit potentially a bad advice. To understand why, have a look at its little sister below.


Controversial alright, but I'd argue that anyone who answers 'no' to this question is missing a fundamental concept of TDD.

For me, the answer is a resounding yes if you follow TDD. If you aren't then no is a plausible answer.

The DDD in TDD

TDD is often quoted as having thee main benefits.

  • Defence
    • Ensuring the code may change but not its behaviour.
    • This allows the ever so important practice of refactoring.
    • You gain this TDD or not.
  • Design
    • You specify what something should do, how it should behaves before implementing it.
    • This often means more informed implementation decisions.
  • Documentation
    • The test suite should serve as the specification (requirements) documentation.
    • Using tests for such purpose mean that the documentation and implementation are always in consistent state - a change to one means a change to other. Compare with keeping requirements and design on separate word document.

Separate responsibility from implementation

As programmers, it is terribly tempting to think of attributes as something of significance and getters and setter as some sort of overhead.

But attributes are an implementation detail, while setters and getters are the contractual interface that actually make programs work.

It is far more important to spell that an object should:

Allow its clients to change its state

and

Allow its clients to query its state

then how this state is actually stored (for which an attribute is the most common, but not the only way).

A test such as

(The Painter class) should store the provided colour

is important for the documentation part of TDD.

The fact that the eventual implementation is trivial (attribute) and carries no defence benefit should be unknown to you when you write the test.

The lack of round-trip engineering...

One of the key problems in the system development world is the lack of round-trip engineering1 - the development process of a system is fragmented into disjointed sub-processes the artifacts of which (documentation, code) are often inconsistent.

1Brodie, Michael L. "John Mylopoulos: sewing seeds of conceptual modelling." Conceptual Modeling: Foundations and Applications. Springer Berlin Heidelberg, 2009. 1-9.

...and how TDD solves it

It is the documentation part of TDD that ensures that the specifications of the system and its code are always consistent.

Design first, implement later

Within TDD we write failing acceptance test first, only then write the code that let them pass.

Within the higher-level BDD, we write scenarios first, then make them pass.

Why should you exclude setters and getter?

In theory, it is perfectly possible within TDD for one person to write the test, and another one to implement the code that makes it pass.

So ask yourself:

Should the person writing the tests for a class mention getters and setter.

Since getters and setters are a public interface to a class, the answer is obviously yes, or there will be no way to set or query the state of an object. However, the way to do this is not necessarily by testing each method in isolation, see my other answer for more.

Obviously, if you write the code first, the answer may not be so clearcut.


tl;dr: Yes you should, and with OpenPojo it's trivial.

  1. You should be doing some validation in your getters and setters so you should be testing that. For example, setMom(Person p) should not allow setting anyone younger than themselves as their mother.

  2. Even if you aren't doing any of that now, odds are you will in the future, then this will be a good for regression analysis. If you want to allow setting mothers to null you should have a test for that should someone change that later on, this will reinforce your assumptions.

  3. A common bug is void setFoo( Object foo ){ foo = foo; } where it should be void setFoo( Object foo ){ this.foo = foo; }. (In the first case the foo that is being written to is the parameter not the foo field on the object).

  4. If you are returning an array or collection you should be testing whether or not the getter is going to be performing defensive copies of the data passed into the setter before returning.

  5. Otherwise, if you have the most basic setters/getters then unit-testing them will add maybe about 10 minutes at most per-object, so what is the loss? If you add behaviour you already have a skeleton test and you get this regression testing for free. If you are using Java, you have no excuse since there is OpenPojo. There are an existing set of rules you can enable and then scan your entire project with them to make sure they are applied consistently within your code.

From their examples:

final Validator pojoValidator = ValidatorBuilder.create()
        .with(
            new NoPublicFieldsRule  (),
            new NoPrimitivesRule    (),
            new GetterMustExistRule (),
            new SetterMustExistRule ()
        )
        .with(
            new DefaultValuesNullTester (),
            new SetterTester            (),
            new GetterTester            ()
        )
        .build();


pojoValidator.validate(  PojoClassFactory.getPojoClasses( "net.initech.app", new FilterPackageInfo() )  );

Roy Osherove in his famous book 'The Art Of Unit Testing' says:

Properties (getters/setters in Java) are good examples of code that usually doesn’t contain any logic, and doesn’t require testing. But watch out: once you add any check inside the property, you’ll want to make sure that logic is being tested.

Tags:

Unit Testing