Skip to content

Why

In the following encounter, an experienced Java Developer interrogates Mean Bean. Some of the developer’s colleagues are already using Mean Bean, and have recommended he check it out. He’s sceptical that it’s yet another test tool to learn though.

Sceptic:

[Blunt] Why should I use you?

Mean Bean:

Ah, that old chestnut again… [Sighs] Three main reasons:

  1. To test the correctness of your JavaBean/POJO public properties.
  2. To verify your compliance with the equals and hashCode contracts.
  3. To confirm which properties are considered significant by your equals and hashCode methods.

Sceptic:

[Exaggerated yawn] My IDE generates getters and setters for me anyway, so why should I bother testing them?

Mean Bean:

What if you switch IDE?

Sceptic:

I won’t. I always use FunkyIDE. [Replace with your favourite IDE]

Mean Bean:

What if the rest of your team doesn’t use “FunkyIDE”, or a similar feature?

Sceptic:

They do. They’re not stupid enough to create all that boilerplate code themselves. That would be crazy!

Mean Bean:

Ok, sure. I agree that using a tool to generate boilerplate code is better than manually entering it all. What do you do though if you need to modify an existing JavaBean/POJO class? Do you delete your getter/setter methods and regenerate them completely?

Sceptic:

Er…  well… no… If I change a property type, say, in a POJO, I’ll just refactor what I need to, like: the member field, the getter method and the setter method. [Looks embarrassed and sees where this is leading]

Mean Bean:

Which means…

Sceptic:

Yeah, yeah… Ok, I suppose if I were a junior programmer I might make a mistake. But c’mon, I’m a pro. I don’t make mistakes.

Mean Bean:

Everybody makes mistakes. It’s human error.

Sceptic:

Very philosophical… [Another exaggerated yawn]

Mean Bean:

You could change the code in the way you’ve described, but what you need is a test suite that will detect if you make a mistake… A safety net that will pick up silly mistakes at the heart of your objects. That’s where I come in.

Sceptic:

Ok, maybe. But FindBugs and similar tools will find the sort of thing you’re worried about.

Mean Bean:

FindBugs and the like are fantastic tools, but they won’t find everything. I’m a specialist in this field. I know just the right buttons to push to make your objects… “spill the beans”!

Sceptic:

You’ve lost me.

Mean Bean:

Well, some have described me as “brutish”, some “excessive”, but I get the job done. I look at every public getter/setter method pair, generate appropriate random test data, invoke each method and assert that the behaviour is correct. [Pauses for effect]

Sceptic:

[Laboured] Ok…?

Mean Bean:

[Continuing proudly] 100 times per method pair. Each test uses different randomly generated test data, so bugs can’t hide from me.

Sceptic:

[Disapproving] Why test so many times?

Mean Bean:

To ensure that the getter/setter methods don’t have hard-coded values in them. Random test data combined with multiple invocations prevents missing those bugs. Don’t worry though, if you think that’s too much, you can change the number of tests per method. I’m quite flexible.

[Sceptic falls silent]

Mean Bean:

[Sees opportunity] And another thing: have you ever inherited an existing project that you had nothing to do with, but now you have to maintain?

Sceptic:

Sure. My boss always lands me with them.

Mean Bean:

Running me on a legacy project is a great way to rapidly up the test coverage at the core of the application: its domain and data objects. You’ll instantly have a warm fuzzy feeling.

Sceptic:

Fine, I guess I can see that might be useful…

Mean Bean:

[Continues regardless] Some people say: “why test getters and setters?” I say, “why not?” After all, it’s code that might have a bug in it and domain and data objects are core to most applications. Especially now there’s a return to more OO design principles made easy by Dependency Injection frameworks like Spring, Guice, …

Sceptic:

[Butting in] Hey! Calm down, you crazy bean! You’ve sold me the whole getter/setter thing, but I’m still not entirely convinced I should use you. Despite the fact I could write code to test my getters and setters myself, didn’t you mention something about equals and hashCode too? Sell it to me. This is your moment!

Mean Bean:

Right. Sorry. Forgot myself there. Ok, well, just for the record, yes you could write your own getter/setter test code, but just think how much time that would take. With me, all you need to do is:

BeanTester tester = new BeanTester();
tester.testBean(YourPojoDomainObject.class);

Easy!

[Sceptic folds arms and waits expectantly]

Mean Bean:

Right. Sorry. Where was I? Yes… Equals and HashCode.

[Sceptic nods]

Mean Bean:

How many items are there in the Equals Contract?

Sceptic:

I dunno… 3? … 4? Something like that. I’m too busy writing business logic and distributed multi-service transactions to remember junior stuff like that.

Mean Bean:

Actually, there are 5. Reflexive, Symmetric, Transitive, Consistent and “Non-Nullity”!

Sceptic:

[Singing mockingly] And a partridge in a pear tree!

Mean Bean:

My point is: there are lots. And you’re right; you don’t want to have to remember that fundamental stuff when you’re developing complex systems. Even if you do want to remember all that, you certainly don’t want to write tests for every overridden equals method in your project.

[Proudly] That’s where I come in.

Sceptic:

How so?

Mean Bean:

All you need to do is specify the class to test and I’ll do everything for you. Look:

EqualsMethodTester tester = new EqualsMethodTester();
tester.testEqualsMethod(YourPojoDomainObject.class);

Easy!

Sceptic:

Fine, I guess. What do I get in return for this?

Mean Bean:

A lot of bang for your buck… I’ll verify your compliance with the Equals Contract, plus I’ll verify that the properties you think are significant in your equals logic actually are significant.

Sceptic:

[Doubtful] Oh yeah? How?

Mean Bean:

[Smiling] I change one property at a time and verify that the equals logic holds as expected. If a property is supposed to be significant to the equals logic, then if I change it between two otherwise equivalent objects, equals should be false. I check all your properties in turn, systematically.

Sceptic:

Wow! You are a bit brute force, aren’t you? That is pretty handy. What if not all properties of an object are considered in the equals method?

Mean Bean:

They’re what I call “insignificant”, in the sense that they should have no bearing on the equality of two objects. I test that too. If the only difference between two objects is an insignificant property then the objects should be considered equal.

Sceptic:

Nice. How do I tell you which properties are significant and which are not?

Mean Bean:

I assume that all properties are significant, unless you tell me otherwise, like so:

EqualsMethodTester tester = new EqualsMethodTester();
tester.testEqualsMethod(YourPojoDomainObject.class, “insignificantPropertyName”);

Sceptic:

Easy!

Mean Bean:

That’s right. [Nodding] Easy!

Sceptic:

What else can you do?

Mean Bean:

I can also verify your compliance with the HashCode Contract. Look:

HashCodeMethodTester tester = new HashCodeMethodTester();
tester.testHashCodeMethod(YourPojoDomainObject.class);

Sceptic:

Cool. Will you also test the significance of properties in my hashCode methods?

Mean Bean:

[Embarrassed] Erm… no… I can’t do that just yet… But, soon! I’ll be able to do that soon!

Sceptic:

[Nonchalantly] I guess I might as well give you a go then… see how you fit in.

Mean Bean:

Great!

Sceptic:

And you’ll keep me posted about the HashCode thing?

Mean Bean:

[Enthusiastically] Sure will! I’ve lots of cool features planned. My goal is to make testing as easy as possible. You just watch!