我正在尝试测试我所拥有的基于一系列其他范围的范围。 (下面的“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>
似乎includes_values是ActiveRecord :: Relation对象的实例变量,但是当我尝试存根时,我仍然收到相同的错误。我想知道是否有人有经验固定Rails 3的新链式查询?我可以找到关于2.x的查找哈希的一堆讨论,但没有关于如何测试当前的内容。
答案 0 :(得分: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}
答案 1 :(得分:3)
与上述相同的答案。
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
答案 2 :(得分:1)
首先,您可能不应该测试内置的Rails功能。
你应该只为自己编写的代码编写单元测试(如果你练习TDD,这应该是第二天性的) - Rails为其内置功能提供了自己的综合单元测试套件 - 没有必要在复制这个。
就错误而言,我认为您的问题就在这一行:
@chain.should_receive(:limit).with(15).and_return(Factory(:entry))
您希望该链返回Factory
,这实际上是ActiveRecord
的实例,但实际上是every relation returns yet another ActiveRecord::Relation
。
因此,您的期望本身是不正确的,并且可能确实导致了被抛出的错误。
请记住,在您明确迭代它们之前,范围实际上不会返回您期望的记录。此外,关系的记录永远不会返回单个记录。它们总是返回一个空数组或一个带记录的数组。
答案 3 :(得分: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