Design for Testability


I've been meaning to blog about a new tool I've been using for some projects for the past month, called TypeMock, but I kept delaying it. Today, after a "debate" on alt.net mailing list, I've decided to say a couple of things and hopefully end the deabte it with this post. So to put you in context, a little background. TypeMock is a mocking framework that allows you to mock objects that don't necessarily implement an interface. This makes it extremely easy to mock objects in legacy code or code over which you have no control over (for example using TypeMock for testing ASP.NET MVC). It also has a very nice and elegant syntax (called Natural Mocks) that makes your tests easy and clean.

There are other frameworks for mocking, such as RhinoMocks or NMock, both of which require classes you want to mock to implement an interface (interface/abstract class). I've been using RhinoMock up to now until I switched recently to TypeMock.

Chad Myers was asking for reasons as to why he should use TypeMock since he already has reasons why not to use it. I responded with two points:

1. It allows you to test legacy code or code you do not have control over.
2. It doesn't force you to implement interfaces just for the sake of testability

And it seems that point 2, with some people didn't go through too well. So for the last time, let me clear it up.

I tend to design my systems with loosely coupled classes where I use interfaces and dependency injection when I need it. What does that mean? It means when I know that there is a possiblity that I might need a different implementation for a particular class. Now beforehand it's not always possible to know what your system might need in the future, in which case I tend to abstract my classes. However, there are certain situations where I do know for sure, 100% guaranteed, that I do not have a need for abstracting a particular class (how often does an RFC protocol implementation change?). These are the times where I do not see a need to introduce dependency injection just for the sake of testability.

Now one argument against that is that if a class is tightly coupled enough so as to not require abstraction, then the unit test should be more an integration test. That's great in theory but not always possible in practice. I might have to perform unit tests on my code where certain dependent classes aren't viable to be tested.

In summary, if I'm using a mocking framework that allows me to overcome these situations, whether caused by my own code or not, and at the same time allows me (nothing can prevent you) to continue with my good practices, I don't see a reason why I shouldn't use it. If on top of that I get a nice syntax and other features all the better. What it doesn't imply is that just because I can now mock concrete classes that I should forget about concepts such as dependency injection.

I still haven't received a response on in this debate about why would you abstract all your classes Maybe it's because of testing frameworks imposing it on your design?  But to be honest, I've given up asking.

Comments: 


Add your comment: 

Name:  
E-Mail:  
URL:  
Comment:  
Please add 5 and 5 and type the answer here: