[rspec-users] should_receive and multiple return values

Pat Maddox pergesu at gmail.com
Mon Dec 18 07:31:41 EST 2006


On 12/18/06, Ashley Moran <work at ashleymoran.me.uk> wrote:
> Hi
>
> I just got bit by a misunderstanding about and_return.
>
> I've got this controller method parse_parameters that loops over
> query string parameters and parses out vehicle registration dates.
> We have to turn these into one of three bands (Jan-Feb, Mar-Aug, Sep-
> Dec) so I wrote a method (registration_date_to_band_year_and_month)
> takes a date and returns two return values, the year and month of the
> band.
>
> I thought this would work:
>
>    specify "should turn the provided registration date into a CAP
> band" do
>      CapFutureResidual.should_receive
> (:registration_date_to_band_year_and_month).with(Date.new(2003, 9,
> 30)).and_return(2003, 9)
>      CapFutureResidual.should_receive
> (:registration_date_to_band_year_and_month).with(Date.new(2005, 3,
> 1)).and_return(2005, 3)
>      controller.parse_parameters(
>          { :capid26149 => "rd2003-09-30,mi40000,ft15", :capid30125 =>
> "rd2005-03-01,mi73825,ft42" }
>        )
>    end
>
> But it doesn't because and_return is setting up multiple method
> calls, not multiple return values.
>
> I don't imagine multiple return values are used that often, but they
> can be handy.  Would there be any use in another method, maybe
> and_return_values or something to allow you to specify them?  Since
> they are possible in Ruby, it makes sense that you should be able to
> specify them in RSpec.
>
> I got around it, of course, using an array return and the * expand
> operator, but I avoid that when I can
>
> Ashley

hrm...when you return multiple values, isn't it actually returning an array?

irb(main):001:0> def foo; return 1, 2; end
=> nil
irb(main):002:0> a = foo
=> [1, 2]
irb(main):003:0> b, c = foo
=> [1, 2]
irb(main):004:0> a
=> [1, 2]
irb(main):005:0> b
=> 1
irb(main):006:0> c
=> 2

It's just that Ruby is smart enough that you don't need the [] in the
return value.  Also, doing multiple assignment works even if you
explicitly return an array:
irb(main):001:0> def foo; return [1, 2]; end
=> nil
irb(main):002:0> a, b = foo
=> [1, 2]
irb(main):003:0> a
=> 1
irb(main):004:0> b
=> 2

So it really should just be and_return([2005, 3])

Pat


More information about the rspec-users mailing list