Jeffrey Palermo (.com)

Sponsors

The Lounge

News

Advertisement

Images in this post missing? We recently lost them in a site migration. We're working to restore these as you read this. Should you need an image in an emergency, please contact us at imagehelp@codebetter.com
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.


Posted Fri, Sep 16 2005 1:52 PM by Jeffrey Palermo

[Advertisement]

Comments

Jonathan de Halleux wrote re: How to mock a static member for test-driven development - level 400
on Fri, Sep 16 2005 5:08 PM
Have you takened a look at TypeMock ?
Jeffrey Palermo wrote re: How to mock a static member for test-driven development - level 400
on Mon, Sep 19 2005 5:04 PM
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?
Maruis Marais wrote re: How to mock a static member for test-driven development - level 400
on Wed, Feb 8 2006 5:39 PM
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
JayFlowers > Mocking Static Classes and Members wrote JayFlowers > Mocking Static Classes and Members
on Tue, Apr 25 2006 11:24 PM
Creative Coding by Eli Lopian wrote 14 facets of TypeMock.NET and Designing for Testability
on Tue, Sep 26 2006 6:51 PM

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

How to mock a static member for TDD « Ren’s Blog wrote How to mock a static member for TDD « Ren’s Blog
on Thu, Feb 21 2008 8:26 AM

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