[rspec-users] Mocking, changing method interfaces and integration tests
pergesu at gmail.com
Fri May 25 17:31:26 EDT 2007
This is something I've kind of struggled with over the past few months
. 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
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 , 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.
Sorry for the length. pat.should be_less_verbose
(for some reason it doesn't feel right to link to my blog and MF's
bliki together :)
More information about the rspec-users