Interfaces and isolation

Roy Osherove has suggested a new name for mocks, fakes, stubs or any test double: Isolation.  True, the myriad of test double names can muddy the language, and Meszaros’ suggested name of “test double” still confuses people that don’t get the “stunt double” comparison.

When I first started using mocking frameworks, before I understood the OO design techniques they were intended to support, I used primarily two methods in Rhino Mocks:

  • MockRepository.CreateMock
  • Expect.Call

Using these two techniques of creating Mock objects and setting expectations, without good OO design, led to a lot of over-specified, brittle tests.  Setting expectations that seemed to mirror the system under test seemed to be rampant duplication and hindrances to change.  Over time, as I started to learn more about good OO design and the SOLID principles, the issues of brittle and over-specified tests simply went away.  Techniques such as:

  • Dependency inversion principle
  • Interface-based design
  • Command-query separation
  • Single responsibility principle
  • Separation of concerns

All led to better specified behavior in my tests.

Which is why the name “isolation” means nothing to me.

When I’m using interface-based design, I’m doing so not because of some innate desire to increase testability, but because I want to separate concerns and invert my dependencies.  I want users of my class to know exactly what is needed for this class to operate.  I employ fanatical refactoring to ensure the names and responsibilities of the classes I create are clear to the maintainers of my application.

If I employ the DIP and interface-based design, what exactly am I isolating my class from?  Interfaces of which the class already doesn’t care which implementation is provided?  Again, I don’t use interfaces solely to swap out a test double in a unit test, but to achieve clear separation of concerns, hone the single responsibility of the class, and invert the dependencies.

When I use Rhino Mocks in the new AAA syntax, I wind up using only three techniques/methods in 99% of cases:

  • MockRepository.GenerateMock<T> to supply my class under test with any dependencies it needs to work
  • Stub extension method to control indirect inputs
  • AssertWasCalled extension method to verify indirect outputs

Following these rules helps me describe very clear behavior in my tests, with obvious results for those reading the tests.  I don’t need to isolate when I’m already depending upon abstractions.

About Jimmy Bogard

I'm a technical architect with Headspring in Austin, TX. I focus on DDD, distributed systems, and any other acronym-centric design/architecture/methodology. I created AutoMapper and am a co-author of the ASP.NET MVC in Action books.
This entry was posted in TDD. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • Jimmy, thanks for your thoughts.

    first, you “isolate” by surrounding the class with fake dependencies. in production it is not isolated. it has the real implementations attached.

    you still use the “generatemock” method when you should be using “stub”, if you’re asserting that something was called later on. mocks are there to verify against, remember? there should be no more than one mock in any test you write, the rest should be stubs.
    If *you* don’t use the terms correctly, I can imagine lots more people with much less experience abusing them.again, the problem here is that the API uses stub and mock almost interchangeably letting you use each one and thinking about it too much.
    what if it was all just called “fake”?
    would you care?

  • @Roy

    To your second point, whether or not something is a mock or not is how I decide to use it. In practice, all my dependencies are created in a base fixture method call, “CreateDependency”.

    I don’t care what the “GenerateXxx” method is called. It could be called “GenerateFloogle” for all I care, the interesting part is in the Stub or AssertWasCalled parts. I regularly “stub” mocks, but only because that’s what the underlying framework created.

    Personally, I’d like to see the decision about what the test double is taken away at the time of creation. It’s more explicit to have it done at assertion time if you want strict/loose or more advanced scenarios.

    I think I understand your first point, but for the system under test, it doesn’t care either way. It’s already isolated.

  • IMO, the introduction of the term “Isolation” means nothing to me nor do I think attempting to explain this to beginners would bring about any sort of breakthrough.

    IMO, it seems like Roy is just putting forth a concept that fits nicely with TypeMock “Isolator”.

    Intoducing new concepts around mocking/stubbing is not going to make it any easier to explain the idea to beginners. This is where good old fashioned teaching comes in. I’ve done quite a few presentations on tdd and have found that ALL beginners have a hard time with at first, but soon realize the concepts behind mocking/stubbing/whatever you want to call it.

    IMO, this brings nothing to the table and adds no benefit to the tdd world. In reference to his post, how is “mocking” an overloaded word? Is it really that confusing to newcomers? Not really.

    I can see this doing more harm than good as you now have one mocking framework changing its language which in turn will confuse more people as to what the difference is between isolation and mocking? tisk tisk!

  • that was my point with fakes: that you don’t care if its a stub or mock until you verify that something was called.

    Isolate – easier for people to grasp than learn two new words. Fake – same thing.

    “already isolated” I think in my words you mean “easily isolatable”

  • schambers:
    The name of the tool was taken from these concepts, not the other way around. It’s called “putting your money where your mouth is”.

  • Mocks, stubs, test spys, etc…

    It is annoying having some many terms. I understand the message of Roy’s post. I don’t think it was simply to push forward the word “isolate” vs. the others, but that the mock object frameworks can be confusing to people due to the terminology. It does increase the barrier to entry. I fully admit that I struggled in the begging with learning TDD. The overloaded terminology involving mocking frameworks does not help.

  • @joey

    Yeah I agree with a lot of the message…I just don’t like “isolate”, I’m already isolated. Interfaces do that for me.

  • @ jimmy

    “Isolate” may not be the best term. Roy also mentions “Fake”, which may be a better way to introduce mocking. I guess a better question is how do you introduce mocking and everything but the kitchen sink?

    Side note, I should _really_ re-read my comments before posting … :)

  • Great post and I agree with the core message.

    “Using these two techniques of creating Mock objects and setting expectations, without good OO design, led to a lot of over-specified, brittle tests. ”

    Maybe true but when I’ve seen people creating over-specified its often been because they:

    1) used a mock when they should have used a stub
    2) used a mock because they did want to test interacitons but they set too many expectations, either on method calls that weren’t important ot the test or on thingsl ike arguments/number of calls
    3) took mocking too far (e.g. into the domain or where it wasn’t useful).