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

Reply via email to