I’ve recently read The Art of Unit Testing by Roy Osherove which I found very useful for helping me establish how to define a good unit test.
One key aspect of the guidelines Roy puts forward are to make sure that one test only tests one thing, which is part of the following guidelines he puts forward:
- Make sure the test tests one thing only (p. 179)
- Make sure the test verifies only on a single call to a mock object. Verifying multiple calls on a mock object is either over specification or testing multiple things.
One good way to help achieve this is by having a single assert in each unit test.
However if the unit test is to validate the behaviour of a method returning an object which specific properties, how can this be verified with a single assert? It seems the possible answers are:
- Don’t, just use multiple asserts to validate each expected property of the returned object
- Override
Object.Equals
andObject.GetHashCode
(In C#) so that the two objects can easily be compared. - Use a framework that allows for two objects to be compared (For example http://comparenetobjects.codeplex.com/ in C#)
3
I think there’s too much ideology in unit testing. 1 assert per test is such an example.
Unit testing is about testing a unit, ie one thing. So if you have a class with 5 properties on it, its perfectly acceptable to hit all 5 props to see if they work. If any of them fail, the test fails.
It makes no difference to attempt to test each of the 5 properties in individual tests – if any one of them fails, you gain nothing. (I assume you write enough info to tell which assertion has failed, and some logging or other diagnostics to tell why it failed). In short, your object failed and you have to fix it. If you need more detail that that, you need a lot more detail than you get from a single assertion anyway.
What I wouldn’t do is try to test many objects in a single test.
Find a sweet spot between too many unit tests and overly large unit tests.
The other answer is a great, pragmatic answer. I will take a different stance, however.
While I agree that asserting one thing can be more general than people often make it out to be, in your particular situation, you have mentioned the correct answer.
.Equals()
and .GetHashCode()
exist. Your object has them. They are currently useless. Any solution other than implementing them is leaving a potential weak point later on. Object comparisons are important, and likely to be reused. Moreover, having the methods you call actually do useful things is highly beneficial.
While it may seem like a waste as you don’t intend to reuse them, that argument does not apply to these two methods because they are a fundamental part of the language.
1