14

他のスコープのチェーンに基づいているスコープをテストしようとしています。(以下の「public_stream」)。

scope :public, where("entries.privacy = 'public'")
scope :completed, where("entries.observation <> '' AND entries.application <> ''")
scope :without_user, lambda { |user| where("entries.user_id <> ?", user.id) }
scope :public_stream, lambda { |user| public.completed.without_user(user).limit(15) }

次のようなテストを使用します。

    it "should use the public, without_user, completed, and limit scopes" do
      @chain = mock(ActiveRecord::Relation)
      Entry.should_receive(:public).and_return(@chain)
      @chain.should_receive(:without_user).with(@user).and_return(@chain)
      @chain.should_receive(:completed).and_return(@chain)
      @chain.should_receive(:limit).with(15).and_return(Factory(:entry))

      Entry.public_stream(@user)
    end

ただし、引き続きこのエラーが発生します。

Failure/Error: Entry.public_stream(@user)
undefined method `includes_values' for #<Entry:0xd7b7c0>

include_valuesはActiveRecord::Relationshipオブジェクトのインスタンス変数のようですが、スタブしようとすると、同じエラーが発生します。Rails 3の新しい連鎖クエリをスタブ化した経験がある人はいないでしょうか?2.xの検索ハッシュについて多くの議論を見つけることができますが、現在のものをテストする方法については何もありません。

4

4 に答える 4

21

これには rspec を使用stub_chainします。次のようなものを使用できる場合があります。

some_model.rb

scope :uninteresting, :conditions => ["category = 'bad'"],
                      :order => "created_at DESC"

コントローラ

@some_models = SomeModel.uninteresting.where(:something_else => true)

スペック

SomeModel.stub_chain(:uninteresting, :where) {mock_some_model}
于 2011-01-19T01:02:11.340 に答える
4

上記と同じ答え。

SomeModel.stub_chain(:uninteresting, :where) {mock_some_model}

Rspec 3 バージョン:

allow(SomeModel).to receive_message_chain(:uninteresting).and_return(SomeModel.where(nil))

参照:

https://relishapp.com/rspec/rspec-mocks/docs/method-stubs/stub-a-chain-of-methods

于 2014-04-16T16:56:08.543 に答える
1

まず、組み込みの Rails 機能をテストするべきではありません。

自分で書いたコードの単体テストだけを書くべきです (TDD を実践しているなら、これは当然のことです) – Rails には、組み込み機能用の独自の包括的な単体テスト スイートが付属しています – これを複製しても意味がありません.

エラーがスローされている限り、あなたの問題は次の行にあると思います:

@chain.should_receive(:limit).with(15).and_return(Factory(:entry))

チェーンが を返すことを期待していますがFactory、これは事実上 のインスタンスになりますActiveRecordが、実際にはすべてのリレーションがさらに別の を返しますActiveRecord::Relation

したがって、あなたの期待自体は正しくなく、実際にスローされているエラーを引き起こしている可能性があります。

スコープは、明示的に反復処理を行うまで、期待するレコードを実際には返さないことに注意してください。また、リレーションのレコードが1 つのレコードを返すことはありません。それらは常に空の配列またはレコードを含む配列のいずれかを返します。

于 2012-04-09T19:47:50.993 に答える
0

スコープが失われる可能性があるため、Arelを渡してみてください。

it "should use the public, without_user, completed, and limit scopes" do
  @chain = Entry
  @chain.should_receive(:public).and_return(@chain.public)
  @chain.should_receive(:without_user).with(@user).and_return(@chain.without_user(@user))
  @chain.should_receive(:completed).and_return(@chain.completed)
  @chain.should_receive(:limit).with(15).and_return(Factory(:entry))

  Entry.public_stream(@user)
end
于 2011-01-03T18:48:20.903 に答える