[rspec-users] mock assertions on block parameters

Matt Wynne matt at mattwynne.net
Mon Jun 7 11:34:00 EDT 2010


On 7 Jun 2010, at 15:56, Ben Butler-Cole wrote:

> On 7 June 2010 15:25, Matt Wynne <matt at mattwynne.net> wrote:
> 
> Have you seen and_yield? I can't quite get my head around what you're trying to do, but it might help anyway
> 
> Thank you, I have. My understanding is that #and_yield has much the same use as #and_return (in its non-bastardized-by-me-form). That is, you specify it in order to make the mocked-out collaborator behave enough like the real collaborator that the object-under-test can work properly.
> 
> I'll try to explain what I'm aiming for more comprehensibly.
> 
> If I my object-under-test calls a method with a parameter, I can make assertions against the values passed. The simplest is equality:
> 
>   foo.should_receive(:bar).with(6)
> 
> The corresponding code in the object-under-test is
> 
>   foo.bar(6)
> 
> and the real code for the collaborator is something like:
> 
> class Foo
>   def bar(x)
>     // ...
>   end
> end
> 
> Now the collaborator in my case doesn't take a parameter, it takes a block:
> 
> class Foo2
>   def bar2(&block)
>     // ...
>   end
> end
> 
> and the object-under-test passes in a block which is called later for its return value:
> 
>   foo2.bar2 { 6 }
> 
> (The real block doesn't return a constant, obviously. It returns something which needs to be evaluated lazily because its dependencies don't exist yet.)
> 
> I want to test that the block passed in is the block that I expect. Something like (in an imaginary world):
> 
>   foo2.should_receive(:foo2).with(block(yielding(6)))
> 
> (In fact, in my case I can't just assert equality on the return value from the block. I'm actually going to test its type.)
> 
> The corresponding test using my obscene #and_return hack looks like this:
> 
>   foo2.should_receive(:foo2).and_return { |block| block.call.should ==6 }
> 
> But this doesn't scale to multiple calls to #foo2 in the object under test because RSpec (understandably) matches its expectations against invocations based on method name and argument matchers.

I'm still not quite clear what you're trying to achieve. Do you want to assert that a specific block is passed to the collaborator, or do you want to assert that any old block with a particular behaviour is passed to the collaborator?

If it's the former, you can test it by creating a test double for the block, and asserting that it's passed to the collaborator, like this:
http://gist.github.com/428801

Does that help?


> 
> -Ben
> 
> _______________________________________________
> rspec-users mailing list
> rspec-users at rubyforge.org
> http://rubyforge.org/mailman/listinfo/rspec-users

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://rubyforge.org/pipermail/rspec-users/attachments/20100607/a2898a09/attachment.html>


More information about the rspec-users mailing list