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

Jeffrey Palermo [MVP]

Software management consultant and CTO, Headspring Systems

How to mock a static member for test-driven development - level 400

If you are interested in mocking a static member or class in order to facilitate testing a component in isolation, you are traveling down the wrong path.  First, to be blunt, you cannot mock a static.  Static members belong to the AppDomain, and are not replaceable instances.  For instance, if I have a class with static methods called SqlHelper (like version 2 of the DAAB), and I want to unit test a class that calls methods on SqlHelper, I'm stuck.  I can't do it.  SqlHelper's static methods call directly into data access code, so now anything that calls SqlHelper has a transitive dependency on the data access code (and most likely the database behind it). 

So you have code that can't be tested in isolation.  What do you do? 

  • Don't waste you time trying to find a solution to mocking the static members of SqlHelper.  You can't do it.  Just like you can't run Java Swing code inside a WinForms .Net project - there's no point in searching for a solution because one doesn't exist). 
  • Refactor your code because your component is highly coupled.  You desire loosely coupled code.  Change your SqlHelper class's static members into instance members, or if you can't, wrap it in another class - let's call this SqlRunner.
  • Accept an instance of SqlRunner in the constructor of the component you are testing; save it in a class-level variable.
  • Unit test to your heart's content.

It's really that simple.  In your test, you can create a dynamic mock of the SqlRunner class and pass that into the constructor of your tested component.  Your component will now call out to your mock, and you have succeeded in testing your component in isolation. 

You may be wondering what to do if you need to call some static members in the .Net framework.  For instance, what about HttpContext.Current in a web control?  Current is a static property that returns the current instance of the HttpContext class.  You do not want to call that property directly in your code if you ever hope to test it.  In that case, use the same technique as above with a thin wrapper class that knows how to get HttpContext.Current.

If you still aren't convinced about the rigidity of statics in code, feel free to keep searching, but when you come back around and follow the above steps, come back and leave a comment.



Comments

Jonathan de Halleux said:

Have you takened a look at TypeMock ?
# September 16, 2005 5:08 PM

Jeffrey Palermo said:

Yes, I have looked at TypeMock, and it's trying too hard. The solution to mocking a static isn't to subvert the runtime but to change the static to an object that works _with_ the runtime.

You can make a pig fly by shooting him out of a cannon, but you'll kill your pig in the process.

Using statics all over the place will kill your software. Perhaps you called my bluff when I said "you cannot mock a static." Ok, you win. My next question is: Do you really _want_ to mock a static?
# September 19, 2005 5:04 PM

Maruis Marais said:

A colleague and I have been talking about Design for testability over the past couple of weeks. The conclusion we came to was that to be able to design for testing, you really need to understand and have good OO knowledge. You need to understand why two objects have high coupling (which normally mean the objects are hard to test) and why cyclomatic complexity is an important metric to keep your code simple.

The following areas need to be addressed to be able to do effective TDD:

OO principles – like always code against interfaces
Refactoring - without this knowledge the TDD mantra is nullified
Design Patterns – to know how to solve those recurring problems

People also needs to understand where and what to test. I’ve found a lot of beginners don’t understand the difference between Unit Test and Functional tests. They write unit test at a functional test level and then don’t understand why the tests are brittle and break constantly.

Ideas like Mocking and stubbing is also important, but they do depend on design for testability. You need to grasp concepts like dependency injection to take full advantage of mocking frameworks.

I’ve posted on how to use TypeMock.NET to replace an external dependency in a SOA type application. You can find the article at the following link:
http://exceptionz.blogspot.com/2006/01/using-typemocknet-to-mock-external.html

cheers,
Maruis Marais
# February 8, 2006 5:39 PM

Creative Coding by Eli Lopian said:

There has been much talk about Designing for Testability lately.Basically the argument is: Should our Tests (Enabling Mock Insersions) Drive our design? or should we use tools to do it for us?Here is what 14 of are our community have to say about it:Still

# September 26, 2006 6:51 PM

How to mock a static member for TDD « Ren’s Blog said:

Pingback from  How to mock a static member for TDD « Ren’s Blog

# February 21, 2008 8:26 AM

About Jeffrey Palermo

Jeffrey Palermo is a software management consultant and the CTO of Headspring Systems in Austin, TX. Jeffrey specializes in Agile coaching and helps companies double the productivity of software teams. Jeffrey is an MCSD.Net , Microsoft MVP, Certified Scrummaster, Austin .Net User Group leader, AgileAustin board member, INETA speaker, INETA Membership Mentor, Christian, husband, father, motorcyclist, Eagle Scout, U.S. Army Veteran, and Texas A&M University graduate. Check out Devlicio.us!

This Blog

Syndication