The trouble with mocks (or design versus acceptance)

I had the pleasure of speaking to Luke Redpath the other day.

I started off by thanking him for his Demeter’s Revenge plugin, which is one of the first things I install on a new project. He said he didn’t use it much any more, as he doesn’t do mocking, except during the design process. This surprised me, but thinking about it, the distinction between what your different types of tests are for is an important one.

The most important part of using mocks is their value in designing your class’s public API. You start with a cucumber feature (your acceptance test) and as you are implementing it, fill in specs for each component in turn. As features are defined in terms of the user interface, you start by specifying and designing your view and controller. The controller needs to interact with a model. And this is where mocking comes into its own.


describe WotsitPokesController
  it "should poke a wotsit" do
    on_posting_to :create, :id => '1' do
      @wotsit = mock_model Wotsit
      Wotsit.should_receive(:find).with('1').and_return(@wotsit)
      @wotsit.should_receive(:poke).and_return(true)
    end
    response.should redirect_to(edit_wotsit_path(@wotsit))
    flash[:notice].should == 'Your wotsit has been poked'
  end

(this uses the RSpec-Rails Extensions to tidy up the specification)

Whatever @wotsit.poke does, when you are mocking, it is in your interests to encapsulate its behaviour within a single method. Otherwise you end up writing tons of “fake” code within your spec, which makes the tests brittle and hard to maintain.

A small housekeeping note; as soon as your controller spec references @wotsit.poke, you need to go to your model spec and add:


  it "should poke itself"

A pending specification, just as a reminder that you’ve got a method to implement in a few minutes time.

But Luke had started doing full-stack testing alone; using shoulda (with its nested contexts) to write acceptance tests, rather than RSpec and mocking.

I’m not so sure about this. His reason was the brittleness of mocked tests. Agreed, it can be dangerous; if you rename the “poke” method on your Wotsit, your controller spec will still pass. But, crucially, your cucumber story (or shoulda integration test) will not.

So I guess the point to make here is that specifying with mocks alone can be a bad idea. You need a full-stack test to catch the stuff that “falls between the cracks”, the proof that your application does what it is supposed to do.

Can you just forego the mocks completely? I don’t think so; they are too valuable during the exploration/design phase.

Should you just get rid of the mocks once your acceptance test is passing? Luke says yes. I’m still undecided, but certainly am tending towards no.

So, what’s your take? Are mocks too brittle to be used in long term development? Or, coupled with an acceptance test, is the value they give so great we need to keep them in our test suite?

(interestingly, since I drafted this post, Pat Maddox has also written about much the same subject with a similar outcome – including Matt Wynne stating “Acceptance tests are for regression coverage, unit tests are for design” in the comments, although Pat himself says you can delete the specs once the design is done).

Tags: , , , , , , , ,

This entry was posted on Thursday, March 12th, 2009 at 5:26 am and is filed under General. You can follow any responses to this entry through the RSS 2.0 feed. Both comments and pings are currently closed.

2 Responses to “The trouble with mocks (or design versus acceptance)”

  1. Double Shot #413 « A Fresh Cup Says:

    [...] The trouble with mocks (or design versus acceptance) – The debate about mocks in testing will never end. [...]

  2. Markus Says:

    I’m switching from BDD back to TDD too, like Luke.

    About mocks, I used them for controllers in the past, like many BDD developers, but I don’t use them anymore. I think mocks should not be used to mock your own cod, they should be used to mock external resources or libraries over which you have little or no control. Mocking in controllers might be great for prototyping your application, but as your app grows you should remove those mocks and add real objects, since these objects are part of the application structure and they’re not external… and you are testing them too when you do this. In fact, these types of “temporary” mocks should be called fakes instead, since they are there to simulate a untested piece of your own code, which you have to refactorize further.

    These ideas aren’t mine though, all these ideas were wrote down by Kent Beck in his “Test Driven Development, By example”, he talks exactly about that, fakes to quickly get “green bars” and begin to refactor, and mocks to simulate external libraries or resources.