TDD Design Starter Kit – Static Methods and Singletons May Be Harmful

Static methods can be a cool solution to many issues and they’re definitely convenient. I routinely use static methods in place of specialized constructor functions. Sometimes it is absolutely necessary to maintain state between method calls or across threads and static methods are a logical choice. However, sometimes static methods do not mix well with Test Driven Development. A direct reference to a static method from one class to a second class means that the first class is strongly coupled to everything that the second class uses. Keeping any kind of state in static members can also interfere with your unit tests (more on that here). Always be cognizant of this fact before you create a static method.

Just to get this one out of the way, you cannot mock (or stub) a static method, period. Crying or wailing about it won’t help. There is no easy way to substitute in a stubbed implementation for a static method. For that reason alone, I advise developers to never do anything in a static method that calls out of the current AppDomain (HttpContext objects, database calls, MSMQ manipulation, etc.). Even if you need to use a static (or thread local storage or HttpContext storage) field to maintain state, all consumers should access this cached state through some type of abstraction interface for easier testing.

Besides the testability issue, do you really want your application strongly bound to a particular implementation like MSMQ? If you limit the coupling to MSMQ, you can more easily substitute in MQSeries or a call into your company’s new utopian Enterprise Service Bus later. My point merely being that designing to maximize testability often happily coincides with just plain good design or architecture.

Singletons

Singletons always, always, always interfere with writing decoupled and isolated unit tests. There is a lot of interest in Domain Driven Design right now and one of the key concepts in DDD is that often the domain objects are retrieved or persisted through a repository that manages caching and persistence for a domain class or small family of classes. The repository is stateful across requests or classes, so it is a natural candidate for a singleton. Don’t be seduced by the dark side. If you make the repository a singleton, all of the consumers of the repository (and there will be a bunch) cannot be tested in isolation. You can do something to allow you to mock or stub out the underlying data source classes, but take it from me, this sucks (hard). Your unit tests are dependent upon the implementation of the repository class. This makes your unit tests harder to write because there is more code, and harder to understand because you are investing more of the unit test in setting up the internal state of the repository than exercising the consuming class. For a multitude of reasons, it is always important to make your unit tests intention revealing. Mocking the guts of the repository may end up obfuscating the real intention of a unit test.

Here’s an article I wrote on a TDD-friendly alternative on the StructureMap site for exactly this situation with more discussion on the issue: http://structuremap.sourceforge.net/SingletonInjection.htm.

You should also check out Robert Martin’s article Singleton vs. Just Create One. While you’re on the ObjectMentor site, read everything those guys write, it’s all good stuff.

As an aside, one of my friends does a lot of technical interviews for .Net developers for a very large employer in Austin. His weedout question is “what is the difference between a static and an instance method?” He is continually scratching his head on the percentage of people who wash out on this question. I have no idea what to say about that.

About Jeremy Miller

Jeremy is the Chief Software Architect at Dovetail Software, the coolest ISV in Austin. Jeremy began his IT career writing "Shadow IT" applications to automate his engineering documentation, then wandered into software development because it looked like more fun. Jeremy is the author of the open source StructureMap tool for Dependency Injection with .Net, StoryTeller for supercharged acceptance testing in .Net, and one of the principal developers behind FubuMVC. Jeremy's thoughts on all things software can be found at The Shade Tree Developer at http://codebetter.com/jeremymiller.
This entry was posted in TDD Starter Kit. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • QuantumCoder

    This article is outdated….

  • http://codebetter.com/members/yakumoklesk/default.aspx yakumoklesk

    I just have a question. Does this also apply to Factory pattern? Factory pattern has static methods, but those methods creates new instances, so it would act just as a new instantiator rather than a regular static method.

    Thanks.

  • Dave

    Does this apply to extension methods, since they are static methods?

  • http://codebetter.com/blogs/jeremy.miller Jeremy D. Miller

    @Jim,

    This is an OLD blog post. You can use TypeMock for that today. And just for fun, google “TypeMock, statics” and just watch the controversy spill out.

    Yes, you can mock a static method, but should you?

  • Jim Showalter

    In Java, static methods are easily mocked using JMockIt (it’s trivial). Are you saying there is no equivalent to this for .NET?

  • http://codebetter.com/blogs/jeremy.miller Jeremy D. Miller

    Taylor,

    This post was written before TypeMock.

  • http://taylorbarstow.com Taylor

    I’m late to the party, but regardless I disagree with the assertion that “you cannot mock (or stub) a static method, period”. Check out my article about it:

    http://taylorbarstow.com/2007/10/21/unit-testing-with-static-classes-and-singletons

    Taylor

  • http://community.devpinoy.org/blogs/joeycalisay/ jokiz

    i’m starting out with unit testing and this isue on static methods and singleton has started to bite me. thanks a lot for this post sir!

  • http://www.coveryourasp.net/ James Shaw

    “Sometimes it is absolutely necessary to maintain state between method calls or across threads and static *methods* are a logical choice”

    Don’t you mean static *members*? Static methods have nothing to do with state..