【问题标题】:RSpec: expect.to receive fails if object is not referenced directlyRSpec:如果未直接引用对象,则期望接收失败
【发布时间】:2015-06-03 15:01:57
【问题描述】:

在我的 Rails 应用程序中,我有一个 User 模型:

class User
  def self.foo
    User.all.each{ |user| user.bar }
  end

  def bar
  end
end

在我的规范文件中,我想检查foo 是否为每个用户调用bar,到目前为止,这就是我所拥有的:

describe '::foo' do
  let!(:users) { Fabricate.times(5, :user) }

  it 'calls bar for every user' do
    users.each do |user|
      expect(user).to receive(:bar)
    end

    User.foo
  end
end

虽然该方法被调用(我调试过它,所以我很确定)规范是红色的。

我还尝试编写这段代码来了解问题出在哪里:

let!(:user) { Fabricate(:user) }

it 'fails' do
  expect(user).to receive(:bar)
  User.first.bar
end

it 'pass' do
  expect(user).to receive(:bar)
  user.bar
end

如果我直接引用我的实例,它似乎可以工作,如果我从数据库中获取它,则期望不起作用。

我使用 mongoid,不确定这是否相关。

【问题讨论】:

  • user.bar 有效,user 对象定义了 bar 方法并对其作出响应。

标签: ruby-on-rails rspec mongoid


【解决方案1】:

我认为由于 RSpec 的工作原理,它无法完成:当您设置期望时,RSpec 本质上是“包装”对象,以便它可以跟踪收到的消息。

但是当实现代码从数据库中获取记录时,它们并没有被包装,所以 RSpec 无法记录它们的消息。

RSpec 确实有一个方法 allow_any_instance_of 在某些情况下可以提供帮助,但不鼓励使用它,并且认为它不适合这里。

在这种情况下,我建议存根User.all 以返回一些双打(两个应该就足够了)。然后,您可以验证每个人都调用了bar

【讨论】:

  • 看起来有道理,我会试试你的建议,如果可行的话,我会接受你的回答。
猜你喜欢
  • 2017-07-28
  • 2014-05-13
  • 1970-01-01
  • 2016-05-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多