I've been thinking about this a bit ever since Zach Dennis brought up the issue on another rspec-expectations ticket [1]. I've come up with a proof-of-concept matcher that works pretty well, I think [2]. Here's how you use it:
expect { |b| 3.tap(&b) }.to yield_value(3) The argument passed to the expect block is a little weird, given that no other block expectations take a block argument like this. But I don't see a way around it--for the matcher to detect whether or not an argument is yielded (and what the argument is), it needs to control the block passed to the method-under-test. One big win here over some of the other suggestions I've seen is that it works just fine with the current rspec-expectations API (in contrast, some of the other suggestions I've seen would special-case this matcher so that `expect` takes multiple arguments for it to work). I also like that it's built as a block expectation; to me it is in the same category of matchers as the change, raise_error and throw_symbol matchers: it's something that happens as the result of running a bit of code. If enough people like this we can work on getting it into rspec- expectations as an officially supported matcher. If we did, I'd want to beef it up to be significantly more flexible: # for methods that yield multiple arguments to the block... # yield_value would accept a splat of args, and yield_values would # be a more-grammatically-correct alias. expect { |b| foo.fizz(&b) }.to yield_values(:a, 15) # I'd advocate the matcher using the === operator w/ the given values, # so either of these would work expect { |b| "abc".gsub("a", &b) }.to yield_value(String) expect { |b| "abc".gsub("a", &b) }.to yield_value(/a/) # for cases where you need more control over matching the yielded value, pass a block expect { |b| foo.fizz(&b) }.to yield_value { |val| val.should be_fizzy } Thoughts? [1] https://github.com/rspec/rspec-expectations/pull/119#issuecomment-4520633 [2] https://gist.github.com/2065445 _______________________________________________ rspec-users mailing list rspec-users@rubyforge.org http://rubyforge.org/mailman/listinfo/rspec-users