[rspec-devel] [ rspec-Patches-12841 ] Allow stubs to yield consecutive values

noreply at rubyforge.org noreply at rubyforge.org
Sun Aug 12 19:13:58 EDT 2007


Patches item #12841, was opened at 2007-08-06 02:13
You can respond by visiting: 
http://rubyforge.org/tracker/?func=detail&atid=3151&aid=12841&group_id=797

Category: None
Group: None
Status: Open
Resolution: None
Priority: 3
Submitted By: Pat Maddox (pergesu)
Assigned to: Nobody (None)
Summary: Allow stubs to yield consecutive values

Initial Comment:
Scott Taylor asked,

I have a mock of an instance of a class which descends from Array:

class ArrayDescendent < Array; end

#... in the specs...
@descendent = mock ArrayDescendent

How would I stub out ArrayDescendent#each, which is inherited from
Array, to return multiple values successively?  I could use
and_yield, but that is raising an arity error (the anonymous function/
block should expect only *one value at a time, but and_yield is
yielding both values once).  Should I be using a lambda expression here?




This patch provides the #and_yield_consecutively method for mocks and stubs.

----------------------------------------------------------------------

>Comment By: Aslak Hellesøy (aslak_hellesoy)
Date: 2007-08-12 19:13

Message:
This should be done in the same way as and_return(*consecutive_values)

----------------------------------------------------------------------

Comment By: David Chelimsky (dchelimsky)
Date: 2007-08-12 18:48

Message:
Right now you can do this to get consecutive yield values:

obj.should_receive(:msg).and_yield(value1)
obj.should_receive(:msg).and_yield(value2)

The problem with putting all the values to be yielded in one statement is that rspec would have no way of knowing definitively what is a single array argument vs an array of consecutive arguments.

Conceivably, we could so something like:

obj.should_receive(:msg)
  .and_yield(value1)
  .and_yield(value2)
  .and_yield(value3)
  .and_yield(value4)

But is that really that much of an advantage?

----------------------------------------------------------------------

Comment By: Pat Maddox (pergesu)
Date: 2007-08-06 03:06

Message:
I'm not sure why I thought all? was the proper method to
use.  Just collect the return values and pass them back.

----------------------------------------------------------------------

Comment By: Pat Maddox (pergesu)
Date: 2007-08-06 02:40

Message:
I realized I should probably explain why this is necessary.

Yielded values represent the input values to an anonymous
function (block).  Since a function can take more than 1
argument, there's no way of knowing whether multiple values
are supposed to be passed in at once or returned
consecutively.  This gives us both options, without any
magic that might introduce arity errors.

----------------------------------------------------------------------

Comment By: Pat Maddox (pergesu)
Date: 2007-08-06 02:31

Message:
A little bit of multi-arity love.

it "should support yielding consecutive values to a *-arity
block" do
  yielded_values = []
 
@obj.stub!(:method_that_yields).and_yield_consecutively(["biscuits",
"and"], ["gravy", "is"], ["good", "eatin"])
  @obj.method_that_yields {|val1, val2| yielded_values <<
"#{val1} #{val2}" }
  yielded_values.should == [ "biscuits and", "gravy is",
"good eatin"]
  @obj.rspec_verify
end

Each group of yielded values is in an array.

----------------------------------------------------------------------

You can respond by visiting: 
http://rubyforge.org/tracker/?func=detail&atid=3151&aid=12841&group_id=797


More information about the rspec-devel mailing list