Inversion of Control is NOT about testability

time to read 6 min | 1003 words

Jacob have an interesting perspective on testability:

The thing is that using Typemock means that you can unit test literally any public method of any public class, regardless of any and all internal dependencies that class might have. And you can do so without changing the design and/or architecture of your software at all.

In other words, using Typemock means that everything is testable. Unit testable. Seriously. Everything.
Which is why I had such a hard time reading Jeffrey Palermo's latest blog post entitled “Inversion of Control is NOT about testability”. Since I know Jeffrey Palermo is a .Net developer, my initial response is a big fat “Duh. He must be using Typemock.” Sadly, this is not the case.

“Testable design” only has value in the things it allows us to do—namely, unit test our classes. If we can unit test our classes as easily no matter what design patterns we choose, then that frees us up to explore other aspects of design choices. It isn't that <le design du jour> ceases to have value, it's just that testability is no longer a factor in evaluating its utility.

So, uh, forget all I just said. Spend lots of time making sure your .Net projects are testable. Also: Typemock sucks. Don't bother going there...

There are so many things that I disagree with in this post, I am not sure where to even begin. Before that, I need to point out, as usual, that TypeMock is an awesome tool, and that it can bring a lot of value to the table. It doesn't fit the way that I , personally, works, but that is a personal opinion, and I am just a little bit biased. I just want to make it clear that this post is not an attempt to dismiss TypeMock or its value.

With that out of the way, let us concentrate on the actual content of the post.

First, there is no silver bullet. TypeMock is wonderful, but it is not the answer to every testability prayer (is there such a thing?). If the code is bad, TypeMock can do a lot to help, but it will still be a PITA to test this code.

Second, it looks like Jacob missing the actual message in Palermo's post about "this is not about testability". Good design is one which preserves separation of concerns, maintain the single responsibility principal, amenable to change, etc. This also happen to be a design that is easily testable, but that is beside the point.

Good design is simple one where each piece of the code does one thing, and is not dependent on everything else in the application. To violate that means that you would run into issues the first time you need to make a modification. The reason that we want to avoid dependencies as much as possible is that we have to avoid the cascading change reaction.

I didn't have to look far for an example, two posts prior to this one, Jacob has given an excellent example why a design that is testable with TypeMock (and thus, holy*), run into problems with real world requirements. This is not my scenario, it is his. I can come up with quite a lot of war stories about the problems that code with too much dependencies caused.

Let us take Rhino Mocks as an example (I still think of it as my best work), the project is over 3 years old, started in .Net 1.1 and C# 1.0. It has got through numerous versions and grown through two (and a half :-)) major framework versions. The code is stable and as usable as the the day I started this project. If you dig into Rhino Mocks, you'll find that the code is heavily segregated. That allowed me to add functionality and modify the way things work without difficulty, even when dealing with major changes, like the move to Dynamic Proxy 2 or support the AAA syntax.

That is what you get out of having a good design, software that is maintainable.

* sorry, this is a snipe at Jacob, not TypeMock.