On 20 Oct 2007, at 19:54 20 Oct 2007, Pat Maddox wrote:
> You seem to believe that the only way to define behavior is in terms
> of interactions with other objects. That is flat-out wrong. Please
> read http://martinfowler.com/articles/mocksArentStubs.html.
Thanks for that excellent link. I hadn't read it yet. I need to think
some more :-)
I think one of the reasons I've tended towards all-out behaviour
mocking is that when you start mocking expectations, you often break
outcome-based testing. As a good example, using another variation of
that Account object...
class Account
def initialize(balance_holder)
@balance_holder = balance_holder
end
def balance
@balance_holder.calculate_balance
end
def withdraw(amount)
@balance_holder.decrease_by amount
end
end
Now if @balance_holder is a pretty complex, slow object that cries
out to be mocked, trying to test in the way that you suggested breaks
down:
it "should decrease the balance when an amount is withdrawn" do
@mock_balance_holder.should_receive(:decrease_by).with(100)
account = Account.new(@mock_balance_holder)
account.withdraw(100)
end
In a case like this, it seems to me impossible to avoid specifying
only behaviour, unless you actually create a full-on fake object to
fake the behaviour of the balance_holder (which could be a bit less
trivial than this). But if you've mocked the balance_holder like
that, it is impossible to then test the state of the Account.
I guess the issue comes from situations where the apparently internal
state of an object is dependent on the state of another object. In my
case, I have this happen fairly often when my facebook users, which
depend on a nasty, bug-eyed facebook_session object that I definitely
don't want to interact with in my specs (at least not with the real
version, which is horrendously slow and bug-prone due to various
facebook peculiarities). I don't think that's wrong design, but it
does mean that in those cases you can't use outcome-testing at all
(unless you are writing an integration test).
I'm all for pragmatism but it kind of irks me that I'd have to test
behaviours in some cases and outcomes in others. I suppose neither of
them is black nor white, and David's suggestion that it's all down to
balancing design forces on a case-by-case basis...
Maybe I should get back into maths, so I can have some absolute
truths again ;-)
Thanks to everyone for the very useful discussion, by the way. This
is very helpful, and I'll try to summarize this thought progression
on my blog so that it's not lost...
Daniel
_______________________________________________
rspec-users mailing list
[email protected]
http://rubyforge.org/mailman/listinfo/rspec-users