I've been reading that static methods, static classes, and singletons are evil when you try to implement unit testing in your project. When following the TDD paradigm, should I just forget that they ever existed and never use them again or is it ok to use them sometimes?
Static methods are bad for testability. Even if you succeed, it will affect other tests that rely on the original implementation and lead to mutations that you didn't expect to be.
Static classes have several limitations compared to non-static ones: A static class cannot be inherited from another class. A static class cannot be a base class for another static or non-static class. Static classes do not support virtual methods.
Never say never--static classes and methods have their place in your toolbox.
That said, if the class you are trying to isolate and test (subject under test or SUT) depends on a static class or method, you will be unable to write a test that isolates the SUT from that static dependency--when your test code runs it will still use the static call. Sometimes this is fine, but sometimes you want to create an isolated test that tests ONLY the logic of your SUT with no dependencies (usually via mocking or similar techniques).
In general I personally use static classes and methods relatively sparingly.
Due to the nature of how Singletons are implemented, they present a similar problem for isolating a SUT for unit testing. In addition, the GOF singleton concept is considered to be a bad practice by a certain percentage of software developers. I happen to agree with this sentiment, but there is hardly consensus on this subject. A quick search on google will probably give you a pretty good idea of the pros and cons of the GOF Singleton pattern.
To explain that last part further, instead of attempting to retrieve a value from a singleton within your code, try to initialize the value within a constructor argument. If your constructor grows too large, create a factory method for creation so that you can test your class without using the singleton. If that proves problematic or your singleton has mutable state (I'd be scared of that, but hey, that's me) then try to have it so that your singleton is as easy to incorporate into your testing as possible.
You don't want to have to create an entire configuration file just to test a method on a class which calculates the standard deviation of a block of stock quotes over a 4 hour period. That's too much work. But if your singleton is written in such a way as you can fill it with the data and have another class be responsible for reading in the configuration file and populating that data then you've made great strides forward.
In regards to static methods I'd argue that they're the most easily tested methods you could possible write based on the condition that you don't need to worry about global state. Static are equivalent to y = f(x)
which seems simplistic but underlies the fact that no local state transitions can change the invariant that for a given x
you will always get the same y
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With