在 Rails 3 和 Rspec 中存根链式查询

发布于 2024-09-30 01:31:56 字数 1179 浏览 5 评论 0原文

我正在尝试测试我拥有的基于一系列其他范围的范围。 (下面的“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 的 find hash 的讨论,但没有找到关于如何测试当前内容的讨论。

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.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

乖乖公主 2024-10-07 01:31:56

我使用 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}

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}
绅刃 2024-10-07 01:31:56

与上面的答案相同。

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

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

是你 2024-10-07 01:31:56

首先,您可能不应该测试内置的 Rails 功能。

您应该只为自己编写的代码编写单元测试(如果您练习 TDD,这应该是第二天性) – Rails 为其内置功能提供了自己的全面单元测试套件 – 没有意义复制这个。

至于抛出的错误,我认为您的问题在于这一行:

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

您期望链返回一个 Factory,它实际上是 ActiveRecord 的实例,但实际上 每个关系都会返回另一个 ActiveRecord::关系

因此,您的期望本身是不正确的,并且可能确实导致了抛出的错误。

请记住,范围实际上不会返回您期望的记录,直到您明确地迭代它们。此外,关系的记录永远不会返回单个记录。它们总是要么返回一个空数组,要么返回一个包含记录的数组。

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.

真心难拥有 2024-10-07 01:31:56

尝试传递 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

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文