TypeMock isn’t too powerful, and "Designing for Testability" is much more than merely mocking anyway

Roy has a post up today about TypeMock, testability, and DI.  The age old (ok, it just seems like we’ve been arguing over this for decades) question comes up again “is TypeMock too powerful?”  First, let’s go pro-TypeMock because the attraction of TypeMock is pretty easy to understand.  I’m sick of fighting with C#’s static typing just to write unit tests with mock objects.  Pulling interfaces out just for unit testing is a bit tedious (ReSharper makes both creating the interfaces and bouncing around the code easy enough that that’s not a real problem to me).  It is code noise that’s there for no other reason than to make the compiler shut up.

The fear that TypeMock will “allow” people to write bad designs is partially bogus.  Part of the reason that I think TDD leads to better designs because it’s painful to write tests for bad code (and by bad, I mean code with poor cohesion and poor separation of concerns).  TypeMock will deaden some “pain nerves” that detect bad design by making it possible and even efficient to unit test tightly coupled code (remember that coupling is important for other reasons besides “testability”).  TypeMock usage could easily lead to less reusability and extensibility in the code that may turn out to be harmful in the end.  All the same though, I’m not too worried about people using TypeMock because TypeMock won’t do all that much to help you test bad code.  Let me repeat that again.  TypeMock won’t do all that much to help you test bad code.  Testability is more than just being able to mock interfaces.  Heck, coupling is quite a bit more than mere interfaces. 

If a caller has too much intimate knowledge about the innards of a dependency (tight coupling), setting up the mocking expectations on TypeMock is going to hurt and inform the experienced TDD’er that something is wrong with his or her design.  If a class or method is not cohesive, the test setup will still be too arduous for what you’re trying to test (does the class do only one thing that’s quick to test, or does the thing you want to test only happen in the middle of a bunch of other things).

So, to wrap up:  TypeMock does not end the idea of designing for with testability, and is not going to let you get away with a bad design anyway.
 

As an aside, Dependency Injection and Inversion of Control containers have far more
usages than simply pushing in mock objects.  The existence of TypeMock
doesn’t even remotely eliminate the need or desire for DI/IoC tools
(especially since I very rarely use the container in a unit test
anyway).  Dynamic Languages might signal the upcoming death of the DI tooling, but
TypeMock doesn’t (if StructureMap becomes irrelevant, I just get to move on to new challenges).
 

 

About Jeremy Miller

Jeremy is the Chief Software Architect at Dovetail Software, the coolest ISV in Austin. 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 is the author of the open source StructureMap tool for Dependency Injection with .Net, StoryTeller for supercharged acceptance testing in .Net, and one of the principal developers behind FubuMVC. Jeremy's thoughts on all things software can be found at The Shade Tree Developer at http://codebetter.com/jeremymiller.
This entry was posted in Test Driven Development. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • http://codebetter.com/blogs/jeremy.miller Jeremy D. Miller

    @David,

    I did NOT say that design-for-testability == interface on everything. The very title says Testability > Mockability. READ THE POST BEFORE COMMENTING DAMMIT!

  • David Williams

    I considerably think that its a mistake to insist on confabulating design-for-testability with “I have to have interfaces for everything’ like this post and others on same topics tend to do.”

    [url=http://www.widecircles.com]Social Bookmarking Service[/url]

  • http://codebetter.com/blogs/jeremy.miller Jeremy D. Miller

    @Steve,

    “I think its a mistake to insist on confabulating design-for-testability with ‘I have to have interfaces for everything’ as this post and others on similar topics tend to do.”

    I *was* trying to make exactly that point in this post.

    And in all seriousness, be very, very careful about mocking concrete objects with RhinoMocks. That just doesn’t isolate your tests enough because the concrete class behavior is in there just waiting to come out.

  • http://unhandledexceptions.spaces.live.com Steve Bohlen

    I think its a mistake to insist on confabulating design-for-testability with ‘I have to have interfaces for everything’ as this post and others on similar topics tend to do. Certainly declaring interfaces for everything just to support mocking does add needless ‘noise’ to a design, but explicit interface declaration is hardly the only way to ensure a class is mock-able even without typemock.

    RhinoMocks (and a few other frameworks) support mocking of classes without the need for interfaces so long as the class’ methods are declared virtual (or overridable in VB.NET-ese) — I have used this technique for some time to enable mocking of classes that otherwise don’t need an explicit interface defined for them in order to support the rest of the application’s design.

    Besides, unless you are either hyper-concerned about performance or are 100% sure that nobody will ever need to override one of your methods in a derived class, declaring non-virtual functions is tantamount to declaring the class as sealed: make REALLY sure this is a good idea before you consign some poor maintainer of your app to this23rd ring of hades.

    Bottom line, I think, is that tools like typemock have their place alongside a bunch of other tools (that include sound app design principles) but that assuming that design-for-testability == explosion of otherwise unnecessary interfaces is a fallacy.

  • http://colinjack.blogspot.com Colin Jack

    @Jeremy
    Thanks that link was excellent, ta for posting it.

  • http://codebetter.com/blogs/jeremy.miller Jeremy D. Miller

    @Colin,

    I fixed that sentence. Thanks for the catch.

    Look at James Carr’s list here: http://blog.james-carr.org/?p=44

  • http://colinjack.blogspot.com Colin Jack

    “All the same though, I’m too worried about people using TypeMock because TypeMock won’t do all that much to help you test bad code”.

    Sorry to be pedantic but I think you missed a “not”, which could lead to confusion.

    ” Testability is more than just being able to mock interfaces. Heck, coupling is quite a bit more than mere interfaces.”

    Amen to that.

    “sick of fighting with C#’s static typing just to write unit tests with mock objects. Pulling interfaces out just for unit testing is a bit tedious ”

    I agree. Some people in our team wanted to do interaction testing against our domain classes so we had two choices:

    1) TypeMock – Design as we wanted to.
    2) Rhino – Virtual methods and interfaces all over the domain.

    The second option certainly wouldn’t have improved the design so it was really a bit of a no brainer.

    “So, to wrap up: TypeMock does not end the idea of designing for with testability”

    Having read (and in some cases re-read) some of the stuff at mockobjects.com I don’t think many people use interaction testing in the way these guys originally intended. In addition much of the original documentation on tests driving design was written before interaction testing kicked off properly (unless my memory lets me down).

    “I think the “if testing your code hurts, it’s probably bad” is just a nice feedback loop. I don’t have any masochistic idea that “it should hurt!” TDD is a design activity with a very helpful side effect of unit test coverage.”

    You are probably right, not enough has been written about this topic yet in my view as it is very interesting.

  • http://codebetter.com/blogs/jeremy.miller Jeremy D. Miller

    What I was trying to say is that I don’t think TypeMock really changes TDD in any significant way.

  • http://codebetter.com/blogs/jeremy.miller Jeremy D. Miller

    @Roy,

    I didn’t disagree with anything *you* said, but you were linking to Jacob Profitt’s ongoing “I really don’t like DI” series.

    “But it does sound like you feel that TDD (or “naked TDD”?) is more about test driven design than anything else.”

    I think the “if testing your code hurts, it’s probably bad” is just a nice feedback loop. I don’t have any masochistic idea that “it should hurt!” TDD is a design activity with a very helpful side effect of unit test coverage.

  • http://iserializable.com Roy Osherove

    I addressed DI as a concept, not the DI containers out that that do much more (such as interception AOP style and more). Perhaps the working should have been something like “is DI just for testability irrelevant?”
    I fully agree that it can still be painful to write tests with typemock if your code under test is highly coupled, which is something I neglected to address.

    But it does sound like you feel that TDD (or “naked TDD”?) is more about test driven design than anything else. Perhaps its time to find other ways to drive a better decoupled design than a test framework. It seems though that currently unit testing is as close we get to a self-design-review-in-realtime framework, which I think is not where we should be.
    Roy