Nick Hoffman wrote:
> On 2008-08-27, at 15:25, Mark Wilden wrote:
>> The other thing I would say is that mocking and stubbing are powerful
>> tools that you should add to your arsenal as soon as possible. I've
>> had several coworkers who resisted using them, only to finally
>> achieve that "aha!" moment later. Your tests get easier to write, and
>> they're less brittle to change.
>
> G'day Mark. I was re-reading this thread and noticed this paragraph of
> yours. I've been using RSpec and BDD for about 2 months now, and love it.
>
> However, I'm not a fan of mocking and stubbing, primarily for two
> reasons:
> 1) I believe that specs should test behaviour, rather than a
> behaviour's implementation.
> 2) Using mocks and stubs causes your specs and implementation to be
> tightly coupled, which often forces you to modify your specs if
> changes occur in the implementation.
I'm completely with Zach on this subject, so I won't repeat what he has
stated.  I will however point out that many people who avoid using mocks
simply based on the "test the behaviour not the implementation" argument
fail to realize that the same argument applies just as much to
state-based testing as it does to interaction-based testing (mocking.) 
Coupling a test to the implementation is much more subtle than using
mocks to predefine collaborator interactions.

Consider this glaringly stupid example in which an ambitious first-time
BDDer writes the first spec for a Stack class:

describe Stack do

  describe "#push" do
   
    it "should add an item" do
      stack = Stack.new
      stack.push(5)
      stack.items.should == [5]
    end
   
  end
end

To get this spec to pass they quickly churn out the following code, and
all is green:

class Stack
  attr_accessor :items
 
  def initialize
    @items = []
  end
 
  def push(object)
    @items.push object
  end
   
end

The encapsulation of the Stack is clearly broken by adding the
'attr_accessor :items' call.  Not just that, but the spec is now tied to
how the stack implements it's behaviour. (In fact no  relevant behaviour
was even being speced in the first place, it was all internal
structure!) If the Stack decides to use some other container or method
to implement the behavior then all the specs would need to be changed.

This was a painfully simple example, but the best I could come up with
off the top of my head.  I'm certainly not suggesting that using mocks
here would be better, I'm just illustrating what I believe is meant by
"test the behaviour not the implementation". 

As programs grow in size these sort of issues tend to creep up more
subtlety and such coupling isn't so obvious.  I have noticed that with a
purely state-based approach the creation and testing of objects at the
unit level seems to increase in difficultly and require more setup as
the complexity of a system increases.  Mocks not only allow you to
discover your interface but also help in breaking dependencies and
keeping your unit level specs focused on just that object's
responsibility. 

I should point out however that with every spec I have that uses mocking
I always have an application level test (a story) that executes the same
code with the full stack in motion.  I'm also constantly trying to find
a good balance between state and interaction based testing in my
projects.  I think that balance is different from project to project,
team to team, and developer to developer.  With all that said, I think
mocking is a fantastic tool to have in your tool kit that can help
alleviate a lot of the pain associated with testing and, as Zach
explained, is a great tool to discover your design.

Wow, sorry for the long-winded reply... that was not my intention when I
began to write. :)

As Mark pointed out a good article on the matter is Martin Fowler's:
http://www.martinfowler.com/articles/mocksArentStubs.html

If you read that article would recommend that you follow it up with this
one to get another perspective:
http://nat.truemesh.com/archives/000342.html

-Ben
http://www.benmabey.com
_______________________________________________
rspec-users mailing list
rspec-users@rubyforge.org
http://rubyforge.org/mailman/listinfo/rspec-users

Reply via email to