One of the primary dangers of using mocks is that your unit tests may
be testing against an interface that is different from that of your
production objects. You may simply have misspelled the method (e.g.
object.should_receive(:methd_name) rather than method_name), or you
may have changed the interface of your production object without
updating your tests.
Obviously, you should have some integration coverage that will catch
these kinds of errors (and I do), but it’s nice when they’re caught by
your unit tests since they’re so much faster than integration tests.
I’ve been using a pattern to help with this for a while:
it “safely mocks a method” do
object.should respond_to(:foo)
object.should_receive(:foo).and_return(:bar)
object.do_something_that_calls_foo
end
Basically, I add a respond_to? check before mocking or stubbing a
concrete object (obviously, I don’t do this for a pure mock object).
If/when I rename the mocked method, I’ll get a test failure. I think
it’d be nice to add this to rspec-mocks itself. A few additional
thoughts about this potential feature:
- This would only apply when you’re mocking/stubbing concrete objects;
on a pure mock or stub it wouldn’t do the check. - Should this print a warning or raise an error so the test fails?
- Should it be configurable? I could see some people not wanting this
feature, particularly if you’re strictly following the outside-in BDD
process where the specs on the outer layers (say, a controller in a
rails app) mock methods that have not yet been defined on the inner
layers (say, a model in a rails app). - This feature could potentially take things a step further and when
you specify mock arguments usingwith
, it could check the arity of
the method and be sure that the method accepts that number of
arguments.
What do people think about this idea?
Myron