CodeBetter.Com
CodeBetter.Com
RSS 2.0 via Feedburner
           Do you Twitter? Follow us @CodeBetter

Jeremy D. Miller -- The Shade Tree Developer

Under the hood and working with .Net, TDD, Software Design, and Agile Stuff

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.


Comments

Jeremy D. Miller -- The Shade Tree Developer said:

Here's a handful of articles on designing with or for TDD I had originally posted on my...
# July 21, 2005 1:05 PM

James Shaw said:

"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..
# July 21, 2005 2:37 PM

Jeremy D. Miller -- The Shade Tree Developer said:

My little team is taking over development for one of our other products.  Today is the first...
# August 4, 2005 2:57 PM

Jeremy D. Miller -- The Shade Tree Developer said:

My little team is taking over development for one of our other products.  Today is the first...
# August 4, 2005 3:01 PM

Jeremy D. Miller -- The Shade Tree Developer said:

Mock objects are like any other tool.  Used one way they’re a huge time saver.  In other cases...
# January 10, 2006 6:01 PM

jokiz said:

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!
# May 26, 2006 12:18 PM

Jeremy D. Miller -- The Shade Tree Developer said:

Between being extremely short handed at work, tech' reviewing a new book, a
possible book proposal...
# August 7, 2006 4:51 PM

Taylor said:

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:

taylorbarstow.com/.../unit-testing-with-static-classes-and-singletons

Taylor

# October 21, 2007 2:17 PM

Jeremy D. Miller said:

Taylor,

This post was written before TypeMock.

# October 21, 2007 7:15 PM

Leave a Comment

(required)  
(optional)
(required)  

Enter the numbers above:
Add

About Jeremy D. Miller

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 previously worked as a systems architect building mission critical supply chain software for a Fortune 100 company and learned agile development practices as a .Net consultant at ThoughtWorks, one of the pioneers of agile development. Jeremy is the author of the open source StructureMap (http://structuremap.sourceforge.net) tool for Dependency Injection with .Net and the forthcoming StoryTeller (http://storyteller.tigris.org) tool for supercharged FIT testing in .Net. Jeremy's thoughts on just about everything software related can be found on his weblog "The Shade Tree Developer" at http://codebetter.com/blogs/jeremy.miller, part of the popular CodeBetter site. Jeremy is a Microsoft MVP for C#. Check out Devlicio.us!

This Blog

Syndication

News

All opinions expressed here constitute my (Jeremy D. Miller's) personal opinion, and do not necessarily represent the opinion of any other organization or person, including (but not limited to) my fellow employees, my employer, its clients or their agents.

About Me

"Best Of" Compendium

StructureMap (Dependency Injection for .Net)

StoryTeller (Supercharged Fit)

Build your own Cab

TestDriven

MVP