RSpec:如果没有直接引用对象,则expect.to接收失败

时间:2015-06-03 15:01:58

标签: ruby-on-rails rspec mongoid

在我的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,不确定这是否相关。

1 个答案:

答案 0 :(得分:3)

我认为由于RSpec的工作方式无法实现:当你设定期望时,RSpec基本上会包装'该对象,以便它可以跟踪它收到的消息。

但是当实现代码从数据库中获取记录时,它们不会被包装,因此RSpec无法记录它们的消息。

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

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