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. -Ben -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://rubyforge.org/pipermail/rspec-users/attachments/20100607/fe6d02b7/attachment-0001.html>
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>
On 7 June 2010 16:34, Matt Wynne <matt at mattwynne.net> wrote: 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 >The later. The block gets created by the code under test, so I can''t create a double for it. -Ben -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://rubyforge.org/pipermail/rspec-users/attachments/20100607/3eb1c41c/attachment.html>
On 7 Jun 2010, at 16:52, Ben Butler-Cole wrote:> On 7 June 2010 16:34, Matt Wynne <matt at mattwynne.net> wrote: > > 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 > > The later. The block gets created by the code under test, so I can''t create a double for it.Aha OK. I don''t know how to do that using RSpec''s mocking framework. I''d probably just build my own test double for the collaborator, giving it some simple behaviour to test the block. Something like this: http://gist.github.com/428867 There might be a way to do this using custom matchers[1] but I don''t know how to do it myself. Hopefully someone else will chime in if there is. cheers, Matt [1]http://wiki.github.com/dchelimsky/rspec/custom-matchers> -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/856cadfd/attachment.html>