I'm going to come right out and say it. I love Unit Tests.
I love mocking the collaborators with Mockito (especially the annotation-driven mode). I love the small but oh-so-valuable mini-refactors that are sometimes necessary to make a class testable. And I love watching the code coverage march inexorably to the 100% asymptote.
What makes me very sad is seeing a sorry set of unit tests, and/or a poor development environment for testing. What do I mean?
- If you're not mocking your collaborators, you're not unit testing. And if you're not unit testing, your code is Instant Legacy Code™. You cannot properly test any non-trivial class without needing to mock its dependencies.
- Tests should be named in terms of expected behaviour. Method name testParseIntNullString() says nothing that couldn't be gleaned from looking at the test code itself. Method name shouldThrowFormatExceptionWhenParsingNullString() tells you the intention of both the code under test and the test itself. It's documentation that won't get out of sync with the code.
- Use the facilities provided by your testing package. I'm a TestNG fan, but recent JUnit versions are pretty good too. I use TestNG's groups option in the @Test annotation to specify the style and/or scope of each test method. Another good one is the expected or expectedException annotation option that states what is going to be thrown. Much, much tidier than having try..catch blocks in test methods.
- Code coverage is more than just a percentage. I use the eCobertura Cobertura plugin for Eclipse while I'm writing tests - to visually indicate which parts of the code I'm actually hitting. I've lost count of the number of times it's shown me an if I thought I had covered is still "red" due to a missing precondition.