[rspec-users] Mocking, changing method interfaces and integration tests

David Chelimsky dchelimsky at gmail.com
Fri May 25 18:08:24 EDT 2007

On 5/25/07, Pat Maddox <pergesu at gmail.com> wrote:
> This is something I've kind of struggled with over the past few months
>  [1].  And just yesterday I made the decision to move away from mocks
> in most cases.  That decision resulted from me changing a db column
> name from 'user' to 'username', but one of my tests mocked a
> #find_by_user method, so the test passed even though my code was
> broken.
> Just to note, I've got ~7k lines of Rails spec code that uses mocks,
> and tens of thousands that don't.  So I've used both approaches
> extensively in multiple projects, and have formed the following ideas.
> I think David has a really good point about mock usage being related
> to customer/programmer test coverage.  At this point, we don't have
> any customer tests.  I also don't like the idea of relying on
> heavyweight browser-based tests.  I want to be able to run rake and
> know that my code works.
> Over the past week, I've converted a number of my controller tests to
> use the real implementations instead of using mocks.  It was obvious
> when I realized that in my controllers I'm concerned with state a lot
> more than interaction - a request is made, some state changes, a
> response is given.  I want my tests to prove that those state changes
> are actually being made.  In this way, my controller specs act as
> integration tests.  I do a *tiny* bit of mocking in controller specs,
> in cases where I can't verify state such as making some notification
> request to another machine in the system.
> I'm still using mocks quite a bit in my model specs, and I'm not quite
> sure if I'll be cutting back or not.  Just going to take it a day at a
> time and try to remove any pain.
> You've all surely read Martin Fowler's discussion about
> interaction-based vs state-based testing.  One of the points Dave
> Astels always hammers on about BDD and interaction-based testing is
> that it's not testing, it's a design tool.  I've found that with mocks
> I tend to arrive at a better design earlier on than I do without
> mocks.  I've also found that I can't change the design very easily.
> Mocks are coupled to the design of the code, not the behavior.  Aslak
> says that state-based testing ain't BDD [3], but I disagree.  If I
> can't refactor - changing the design of the code without changing the
> behavior - that doesn't seem very behavior-driven to me.
> Mocks are nice as a design tool, but I've come to accept the fact that
> creating a moderately good design early isn't as useful as having the
> freedom to change my design later on.  I'm just not good enough to
> come up with the perfect design the first time around.  My tests need
> to give me the confidence to refactor.  And I need to be able to run
> those tests quickly from the command line rather than having to start
> up a browser, even if it's automated.  In that regard, mocks just
> aren't for me, at least on my current project.

One thing about TDD and the notion of a "design tool" - it's an
ongoing process. If you want to end up w/ real models in your specs,
you can still use mocks to figure out what they should do, then
replace them w/ the real deal later. This is not nearly as expensive
as it sounds, and lets you focus on one thing at a time.

As for integration testing, what I've found w/ Rails is that if you do
a couple of happy paths with rails built-in integration tests, you'll
expose the refactoring problems that are raising such concern in this
thread. For me, that's a win because you don't have to do the
expensive in-browser stuff, everything's in Ruby, you still can use
mocks to keep the isolation level stuff quick, and you run the slow
integration tests before you commit.

As for mocks tying you to implementation - I see a strong relationship
to how well you follow "Tell, Don't Ask" and the value you get out of
mocking. If you're doing a lot telling instead of asking, you have an
implicitly more loosely coupled design. But if you want to make sure
that the object being described does the telling, there's no better
way to do that then with a mock in my view.

2 more cents.


> Sorry for the length.  pat.should be_less_verbose
> Pat
> [1] http://evang.eli.st/blog/2007/4/9/i-think-i-might-not-get-mocks
> [2] http://www.martinfowler.com/articles/mocksArentStubs.html
> [3] http://blog.aslakhellesoy.com/2006/12/11/the-bdd-cargo-cult
> (for some reason it doesn't feel right to link to my blog and MF's
> bliki together :)
> _______________________________________________
> rspec-users mailing list
> rspec-users at rubyforge.org
> http://rubyforge.org/mailman/listinfo/rspec-users

More information about the rspec-users mailing list