Yesterday I looked over some code and what appeared to be some nice tested code, was a big fail on dependency injection which resulted in his ‘apear to be’ unit tests being completely rubbish.
Most of the code in itself was decent and the author did seem to grasp a lot of the agile principles and patterns. He used dependency injection with unity and the code was written clean and expressive. The average length of his method was no more than 6 lines of code with a clear purpose in mind.
However…
Then I noticed a folder called ‘Utility’. I opened the folder and what I saw was more than a dozen of static classes filled with static ‘Utility’ methods. I scratched my head a bit and then after some hesitation I did alt + f7 (resharper for find all usages) on the utility classes. What I then found was 22 references to these static ‘Utility’ classes throughout his code base.
I then took another look at the test covering the methods that used this Utility method… Then it became clear to me, the unit tests … well … they weren’t unit tests.
How can we unit test a method that uses a static utility method? We can’t.
A "unit" (as defined in the software testing literature) is the smallest piece of code software that can be tested in isolation.
When you are trying to test the method that uses a static method, you can’t mock the behavior of that static method. When you can’t mock calls of the method that needs to be tested then you can’t unit test this method. Why not? Well the calls that this method makes has the potential of changing the behavior of your method under test. Your test won’t be isolated any more to that unit of work, thus it isn’t a unit test.
Consider a static utility method called Util that is used by 4 other methods (respectively A,B,C,D). Imagine now that you’ve written unit tests for all of these methods. Now when the implementation of the utility method changes and there is an error in the behavior of this method, this could trigger a fail on all your unit tests. Should your other methods fail? No A,B,C and D should remain green. Their behavior is just fine under the prerequisite that the method Util behaves fine, but because you couldn’t mock the behavior of the static method you’re stuck with the faulted implementation also being tested in methods A,B,C and D.
So basically you’re not testing 1 unit in your code but you’re testing 2. So you’re depending on the behavior of another method in your tests, which obviously you shouldn’t do.
In conclusion: if you’re doing dependency injection and unit testing don’t use static methods. When you use static method you are in most cases (unless with dirty hacks) bound to the implementation code of that method. In my opinion static methods in general are dangerous and contradictory to object oriented principles.
Until next time ;-)
Geen opmerkingen:
Een reactie posten