Can a RSpec shaded method return different values ​​in a sequence?

I have a Family model with a location method that combines the location outputs of other objects, Members. (Members are related to families, but that doesn't matter here.)

For example, given

  • member_1 has location == 'San Diego (Travel, Returns May 15)'
  • member_2 has location == 'San Diego'

Family.location may return 'San Diego (member_1 travel, returned May 15)' Specificity is not significant.

To simplify testing of Family.location, I want to stub Member.location. However, I need to return two different (specified) values, as in the above example. Ideally, they would be based on the member attribute, but simply returning different values ​​in the sequence would be fine. Is there a way to do this in RSpec?

In each test example, you can override the Member.location method, for example

 it "when residence is the same" do class Member def location return {:residence=>'Home', :work=>'his_work'} if self.male? return {:residence=>'Home', :work=>'her_work'} end end @family.location[:residence].should == 'Home' end 

but I doubt this is a good practice. In any case, when RSpec runs a series of examples, it does not restore the original class, so this view overrides the "poisons" of subsequent examples.

So, is there a way for the wired method to return different, given values ​​for each call?

+48
ruby-on-rails testing stub rspec
May 10 '11 at 9:29 a.m.
source share
4 answers

You can stub a method to return different values ​​each time it calls;

 allow(@family).to receive(:location).and_return('first', 'second', 'other') 

So, the first time you call @family.location , it will return “first”, the second time it will return “second”, and all subsequent times when you call it, it will return “other”.

+105
May 10 '11 at 9:54 am
source share

RSpec 3 Syntax:

 allow(@family).to receive(:location).and_return("abcdefg", "bcdefgh") 
+12
Sep 10 '14 at 15:12
source share

I tried the solution outline above, but it does not work for mine. I solved the problem by performing a replacement.

Something like:

 @family.stub(:location) { rand.to_s } 
0
Sep 01 '14 at 15:01
source share

If for some reason you want to use the old syntax, you can still:

 @family.stub(:location).and_return('foo', 'bar') 
0
Jan 23 '17 at 15:16
source share



All Articles