After spending time in some of my old code this weekend, I've come to the conclusion that developers new to unit testing are likely to bloat their tests.
Since your test has set up some type of state, it's very tempting to test the complete state, rather than the specific behaviour you're looking to validate.
For example, we might have a Save method who's interaction we want to test, so let's start off with a simple test:
[Test]
public void SavingANewUserCallsDataStore()
{
//todo move to SetUp
MockRepository mock = new MockRepository();
IDataStore dataStore = mock.CreateMock<IDataStore>();
User user = User.CreateNewUser();
Expect.Call(dataStore.SaveUser(user)).Returns(39);
mock.ReplayAll();
user.Save();
//todo move to teardown
mock.VerifyAll();
}
Great, the test does exactly what it says it will: it validates that our datastore's SaveUser method is called. While we're at it, why don't we make sure that calling user.Save() did a couple other things? So we add:
Assert.AreEqual(39, user.UserId);
Assert.AreEqual(UserStatus.Normal, user.Status);
The change might seem pretty useful, but we've actually taken a step back. Our test is now doing a lot more than it advertises, which not only makes it less useful as documentation, but also harder to maintain. If either of the two new behaviours we are testing (that the UserId gets set or that the status changes) change, our test will break.
What's worse is that these trivial extras have a tendency to get repeated over and over again, while at the same time never having a dedicated test for the specific behaviour (why bother, we've tested that the userId gets set in 4 other Save tests).
I've read once or twice that unit test should never have more than a single assert. I certainly don't agree with that as a rule, but I understand the spirit in which it was said. I've redoubled my efforts to focus on the specific unit while unit testing, and I'm already seeing the effort pay off. My tests are far more maintainble and understanble. That my friends is a recipe for success.
