"Classic" versus "Mockist" TDD, Distinction Real?

Hot in the Test-Driven Development Yahoo group this week is a discussion concerning the perceived continuum between the so-called "Classic" and "Mockist" approaches to TDD. Steve Freeman, Nat Pryce, Michael Feathers, Dale Emery, and many more discuss terminology and describe their approaches. The discussion also debates whether there even really exists such a continuum, and if so, what distinguishes the approaches that represent it's extremes?

After stating he "feels inclined to the classic-TDD approach", Olaf Bjarnason started the 70+ entry discussion with this question to the group: "What made you switch [to "mockist"] from classic, if you were there before? How does the new method feel?". Many of the early responses though centered more around a challenge Olaf's thread title, "Classic/Mockist discussion". Is there really a need for such a binary distinction?

I think the whole division of TDD practice into "mockist" vs "state based" is pointless, distracting and does a disservice to people trying to learn and use TDD.

Mock objects are just a tool. They are one of many tools that you need to use when doing TDD. Like any tool, they are designed to help solve a set of problems in a specific context. Outside that context they do not help and can be a hindrance.

If this is the case, how then does one know when to apply this "tool"? How does one know to test "state", namely without a mock, versus asserting behavior, namely by using mocks?

Lots of people use the distinction of "state-based" versus "behavior-based." I use a twist on this. I think "result" versus "protocol". If the essence of the test is whether the UUT produced the correct result, I don't usually need a mock for that. If the essence of the test is whether the UUT properly executed its role in a protocol--i.e. whether it sent the right messages to the right collaborators, given the starting conditions and the stimulus--I use mocks to represent the UUT's direct collaborators.

I'd use state-based testing on an object if I had no other way to observe it's behavior - that is if /all/ the call did was change an observable state of the object. Assuming the object actually did something, I'd want to verify [with a mock] that it did it.

For my own part, I *always* mock at system defined boundaries (e.g. filesystem, network, database, etc.) I usually mock when I want to elicit loose coupling between an interface and it's client in a top-down direction. And, I generally don't mock when the object I am interacting with is small and easily faked/stubbed.

As the thread goes on, and as may be highlighted by the above sound-bites from it, there is a recurring observation that while many of these ideas are similarly themed, they don't seem to share a commonly categorizable, named approach beyond "We do it sometimes, but not others". Further, each (with the exception possibly of Sroka's statement about "top-down") tend more to the following: The decision to mock is being driven by the design, as opposed to the converse, where the design is driven by the mocks.

Regarding this idea of using mocks to drive design, Michael Feathers gives an example:

That's an ask. We can do state-based testing of the Errors object in the test.
To make it a tell you'd move to this:

interface ErrorReceiver {
void accept(Error error);
}

ErrorReceiver receiver = ...;
object.reportErrors(receiver);

We can set expectations on a mock receiver and pass it during testing and use a "real" class in production.

Later, largely in response to a post by Steve Freeman (another co-creator of JMock) describing his partner Nat Pryce's categorization of some "mock-worthy peer objects" ("Dependencies","Notifications", and "Policies"), Feathers (and also Colin Jack) assert that the design ideas the duo have been putting forth in fact exist at the core of this "mocks as a tool to drive design" philosophy. Further, more to the point of this thread, that when people talk of a "mockist TDD approach" they are referring in large part to these design ideas, and that the recurring confusion about "Classic vs Mockist TDD" could be reduced if these collection of ideas had a more concrete name.

So, keeping it real, this conversation is really not a new one (Google it), but it is it seems a recurring one. Is there a "Classic TDD", and does it mean "Design begets Mocks"? Is it characterized by something else? Is there "Mockist TDD"? Is it characterized by a "Mocks beget Design" philosophy? "Tell, Don't Ask"? Is it something altogether else? Either way, is it really a "this OR that" thing, or more likely "this for these AND that for those"?

Of course, as always, this news is simply a [hopefully objective] highlight of the Yahoo group discussion, and as such only a piece of the puzzle. Read it for yourself, as well as other sources, and tell others here and/or in the discussion what your experience says.

Perhaps it's more of an argument among those who haven't done TDD for a while. Talking about the distinction and leading people towards state-based testing will keep then from being too extreme and entering an unfortunate place I call "mock hell".

With the knowledge of mocks in hand and the understanding that they are to be used sparingly, new TDDers will find themselves in the balanced place that the gurus on the list (above) are at.

final link in the post "Yahoo group discussion" goes no where:[quote]Of course, as always, this news is simply a [hopefully objective] highlight of the Yahoo group discussion, and as such only a piece of the puzzle. Read it for yourself, as well as other sources, and tell others here and/or in the discussion what your experience says.[/quote]

I personally think its somewhat of an inane argument. If the test is requiring interaction, use a mock. if it requires a change of state use an assert. How this picked up traction.. I really don't know..surely there is some code to written team... get to it!

InfoQ Weekly Newsletter

Join a community of over 250 K senior developers by signing up for our newsletter. If you are based in the EEA, please contact us so we can provide you with the protections afforded to you under EEA protection laws.

Is your profile up-to-date? Please take a moment to review and update.

Email Address

Note: If updating/changing your email, a validation request will be sent

Company name:

Keep current company name

Update Company name to:

Company role:

Keep current company role

Update company role to:

Company size:

Keep current company Size

Update company size to:

Country/Zone:

Keep current country/zone

Update country/zone to:

State/Province/Region:

Keep current state/province/region

Update state/province/region to:

Subscribe to our newsletter?

Subscribe to our architect newsletter?

Subscribe to our industry email notices?

By subscribing to this email, we may send you content based on your previous topic interests. See our privacy notice for details.

You will be sent an email to validate the new email address. This pop-up will close itself in a few moments.

We notice you're using an ad blocker

We understand why you use ad blockers. However to keep InfoQ free we need your support. InfoQ will not provide your data to third parties without individual opt-in consent. We only work with advertisers relevant to our readers. Please consider whitelisting us.