Stubbing Chained Queries in Rails 3 and Rspec

不羁的心 提交于 2019-11-29 06:38:19

问题


I'm trying to test a scope I have that is based upon a chain of other scopes. ("public_stream" below).

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) }

Using a test like this:

    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

However, I continue to receive this error:

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

It seems includes_values is an instance variable of the ActiveRecord::Relation object, but when I try to stub it, I still receive the same error. I was wondering if anyone had experience with stubing Rails 3's new chained queries? I can find a bunch of discussion over 2.x's find hash, but nothing on how to test what's current.


回答1:


I use rspec's stub_chain for this. You might be able to use something like:

some_model.rb

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

Controller

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

spec

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



回答2:


Same Answer as above.

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

Rspec 3 version:

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

Reference:

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




回答3:


First off, you probably should not be testing built-in Rails functionality.

You should only be writing unit tests for code that you have written yourself (which should be second-nature if you practice TDD) – Rails ships with its own comprehensive suite of unit tests for its built-functionality – there is no point in replicating this.

As far as the error being thrown, I think that your issue is on this line:

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

You are expecting the chain to return a Factory, which would effectively be an instance of ActiveRecord, but in actuality every relation returns yet another ActiveRecord::Relation.

Thus, your expectation itself is incorrect, and may indeed be causing the error that's being thrown.

Keep in mind, that scopes don't actually return the records you expect, until you explicitly iterate over them. Also, the relation's records will never return a single record. They will always either return an empty array or an array with records.




回答4:


Try passing on the Arel, as it might be the case that it scopes are going missing.

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


来源:https://stackoverflow.com/questions/4057221/stubbing-chained-queries-in-rails-3-and-rspec

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!