Classicist vs. Mockist Test-Driven Development

One thing that came up in a couple of sessions of Altnetconf UK was the old saw of classicist vs. mockist approaches to TDD. Martin Fowler has a great, and updated, article on the distinction between the two approaches here. Now I have to confess to being a classicist. I tried being a mockist, but I gave it up because of the dangers of over-specified software. Now I tend to favor test doubles for the areas that are difficult to get under test otherwise as per Michael Feathers. We are also much more inclined to use a stub or fake than a mock.


Now some folks seemed to feel that if you had used concrete dependencies or associations in a test, you were not writing a unit test, and thus not using TDD properly. I see the origin of the unit test mantra, Fowler calls TDD in the classicist model mini-integration tests over unit tests, but I reject the latter accusation that this is not, somehow, TDD. The spirit of TDD in my reading, of Kent Beck, never precluded the use of concrete collaborators.






Maybe its time to stop thinking about unit tests and integration tests, with the implicit zero tolerance for collaborators in unit tests, but simply tests and acceptance tests with the latter being more coarse-grained than the former.



Certainly one advantage for classicists is that we don’t get ‘an interface for everything’ and end up with ICustomer, but interfaces where actually want points of extensibility i.e. where we have role that can have multiple implementations, or at boundaries such as layers. We don’t really have to worry about using solutions such as TypeMock to mock a concrete dependency, and so avoid proliferation of interfaces, because we are often more happy with the concrete object itself.


Usefully, there seems to be a convergence between hard-to-test code for classicists, which is where we tend to deploy mocking frameworks, and the places where we need interfaces, so difficulty seems to help flush out these design points.


I would also suggest that people look to the notion of what Rebecca Wirfs-Brock and Alan McKean call sub-systems or object neighborhoods within the domain. Within a neighborhood I would have few doubts around allowing concrete collaborators in tests, it’s okay to play with the other kids in your neighborhood, but outside of that subsystem, you probably want to use a test double to reduce stranger danger. Of course the class to replace with a test double is the facade which you should pass through to get to that neighborhood anyway, once again reinforcing the notion of TDD driving good design.


 


 


 

About Ian Cooper

Ian Cooper has over 18 years of experience delivering Microsoft platform solutions in government, healthcare, and finance. During that time he has worked for the DTi, Reuters, Sungard, Misys and Beazley delivering everything from bespoke enterpise solutions to 'shrink-wrapped' products to thousands of customers. Ian is a passionate exponent of the benefits of OO and Agile. He is test-infected and contagious. When he is not writing C# code he is also the and founder of the London .NET user group. http://www.dnug.org.uk
This entry was posted in altnetconf, AltNetUK, Fakes, Featured, Mocks, Stubs, TDD. Bookmark the permalink. Follow any comments here with the RSS feed for this post.
  • Pingback: Mocks and Tell Don’t Ask

  • http://nylqoots.com/ Vbbplhmv

    2yyHnD

  • http://www.mockobjects.com Steve Freeman

    Can we find a way to talk about TDD styles without being pushed into opposing corners? We don’t like many of the stylistic failings you complain about either (for example http://www.mockobjects.com/2007/04/test-smell-everything-is-mocked.html). If you’re citing Wirfs-Brock, then we already agree on a lot of ideas, and there’s more than one route to improving what people do.

    We see a lot of TDD with mocks where the coders haven’t really understood the point: too much asking over telling, not enough of a domain model, unfocussed interfaces (like ICustomer). We’re trying to get the ideas across, but there’s a lot of noise on the subject nowadays.

    And one more thing to think about. One of the most valuable results we find from interaction-based testing is the idea of driving the design of a type from the needs of its clients. We can do it with clusters of concrete objects, but we find that working against interfaces helps us be clearer about what the relationships should really be.

  • http://www.mockobjects.com Steve Freeman

    Who are “the mockists” and where is their secret hideout from where they plan world domination? A little less Strawman, please.

  • Greg

    @Colin

    I will blog … got a backlog so may be a day or two.

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

    @Greg
    When you say you use messaging patterns though what do you mean, I think I may be designing the same way but I’m not 100% sure.

  • Greg Young

    There is something to be said also for architecting for a given type of testing. We tend to aim for a non-mocked environment and heavily focus on making that easy for ourselves using things like messaging patterns as opposed to direct interactions.

  • Ian Cooper

    @So bored

    The point is that a number of people made the effective statement that ‘If you use a hammer, you are not doing carpentry, carpenters only use saws’.

  • Ian Cooper

    @Christopher
    I think this is my point. We never used to require unit tests by the strong definition of ‘everything else must be mocked’ for TDD. The operative definition of unit at the time of course was Michael Feathers, which related more to painful tests than divorcing ourselves from concrete collaborators.

    The mockists have moved to a position where now, any concrete dependency, is bad in TDD. Though I assume they don’t include value types in that assertion.

    I’m just saying that I have not moved with them.

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

    Yeah totally agree, in fact this is one of my favorite testing topics :)

    I certainly don’t follow a zero-collaborators approach especially when we’re talking about domain level testing.

  • http://mikehadlow.blogspot.com/ Mike Hadlow

    We had a very similar argument in our discussion on IoC and DI. Roy Osherove made an interesting point that doing unit testing forces you do DI unless you use some heavyweight tool (like Typemock :). So adopting the practice implies adopting an architecture. Sure you can give up unit tests and rely on integration tests, as one chap proposed, but I felt that’s a step backwards.

    So then we started arguing about how fine grained do you make the thing-under-test. I think it’s obviously wrong to think class == component and I like the idea of sub-systems, but the scale of your ‘sub system’ or ‘object neighborhood’ directly affects how finely grained your tests can be. It’s easy to fall into the trap of requiring so much setup to test a large component that it never gets properly done.

    I guess I fall more into the mocking camp than the test double one, maybe I’m one of those developers that Jason says go through a period of over-mocking. It’s a long period in my case :)

  • Jason Neylon

    Perhaps mocking framework should come with a “learn about test doubles first” warning on them? (like Castle Windsor has: http://www.castleproject.org/container/index.html)

    I think developers go through a period of over-mocking in their tests whilst learning these frameworks. Once I learnt more about test doubles it was far clearer to me where mocking was useful and where it was simpler to use fakes etc.

  • So bored

    Ian, please write an article about “Hammer-ist vs. Saw-ist” carpentry.

  • So bored

    The whole “state based vs. mockist” thing is a total fabrication of Martin Fowler. There’s no “versus” to talk about. It’s like discussing “hammerist vs screwdriverist” woodworking. There are tools that are useful for the different things you need to do in TDD. Learn to use the tools. Learn to know when to use each kind of tool. End of story.

  • Zubair Khan

    Amen Ian, this is exactly the point I tried to make at ALT.NET UK. There’s always a balance to applying practices, and I don’t think TDD forces anyone in to an IEverything corner. I wonder if this could be something that the “BDD is TDD but a bit better” discussion could have made clearer for me.

  • http://www.bluespire.com/blogs Christopher Bennage

    Does the term “unit” in “unit test” imply that there is just one thing being tested. I’m okay if you want to use concrete collaborators, but I’m a little resistant to calling those “unit tests”. We need a better vocabulary for all this stuff.

  • http://jimmybogard.lostechies.com Jimmy Bogard

    I do agree that over-eager mocking leads to fragile tests. The mistake is to use static mocks where dynamic mocks, stubs, fakes, or dummies would work just fine. Interaction testing has its place, but overuse leads to over-specification.