1. ホーム
  2. ruby-on-rails

[解決済み] RSpecのスタブメソッドは、異なる値を順番に返すことができますか?

2023-04-20 06:57:11

質問

モデルFamilyにメソッド location をマージする location の出力を統合するもので、他のオブジェクトであるMembersの出力です。(Membersはファミリーと関連していますが、ここでは重要ではありません)。

例えば、与えられた

  • member_1 は location == 'サンディエゴ(旅行中、5月15日帰国)'
  • member_2 は location == 'サンディエゴ'

Family.locationは'San Diego (member_1 traveling, returns 15 May)' を返すかもしれません。詳細は重要ではありません。

Family.locationのテストを簡単にするために、私はMember.locationをスタブ化したいと思います。しかし、私は、上記の例のように、2つの異なる(指定された)値を返すことが必要です。理想的には、これらは member の属性に基づくものであることが理想ですが、単に異なる値を順番に返すだけでもかまいません。RSpecでこれを行う方法はあるのでしょうか?

のように、各テスト例内でMember.locationメソッドをオーバーライドすることは可能です。

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

といった具合ですが、これがグッドプラクティスかどうかは疑問です。いずれにせよ、RSpecが一連の例を実行しているとき、元のクラスを復元しないので、この種のオーバーライドは後続の例を汚染することになります。

では、スタブメソッドが呼び出しごとに異なる指定された値を返すようにする方法はあるのでしょうか。

どのように解決するのですか?

メソッドをスタブ化することで、呼び出されるたびに異なる値を返すことができます。

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

ですから、最初に @family.location を呼び出すと「first」、2回目に呼び出すと「second」、それ以降はすべて「other」を返します。