【问题标题】:mocking ActiveRecord results without stubbing in rspec模拟 ActiveRecord 结果而不在 rspec 中存根
【发布时间】:2016-03-13 20:39:28
【问题描述】:

我正在尝试编写规范来测试某些类调用一堆 activerecord 对象(由范围找到)上的方法。

这不起作用:

#someworker_spec.rb
10.times.map { create(:foo) }.each { |f| expect(f).to receive(:bar)
SomeWorker.perform

#someworker.rb
class SomeWorker
    Foo.some_scope.each(&:bar)
end

因为activerecord返回的是新的对象实例,所以activerecord返回的对象实例永远不会收到那个方法。

我知道我可以简单地存根 some_scope 方法并返回对它们的期望值,但这似乎很脆弱。我宁愿检查正确的foo 对象是否接收该方法。有没有办法让我在上面尝试做的事情?

【问题讨论】:

    标签: ruby-on-rails activerecord rspec


    【解决方案1】:

    你可以用and_wrap_original做到这一点

    expect(Foo).to receive(:some_scope).and_wrap_original {|relation| 
      relation.call.each {|record| expect(record).to receive(:bar)}
    }
    

    这确实改变了一些事情,因为上面对 each 的调用将导致 ActiveRecord 加载关系,而不是在您的 perform 方法中调用 each。它还使作用域返回一个数组而不是一个关系

    【讨论】:

    • Frederick - 唯一的问题是它并没有真正验证预期的 activerecord 模型接收该方法,就像我的(不工作的)代码在问题中所做的那样。是实现这一点的唯一方法,只需在 and_wrap_original 块内添加一个额外的行,它有另一个期望:expect(relation.call.map(&:id)).to match_array(factory_created_objects.map(&:id)) ?
    • 当然可以,但我个人只是单独指定范围。
    猜你喜欢
    • 2020-02-26
    • 2011-06-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-27
    • 2021-08-27
    • 2014-09-11
    相关资源
    最近更新 更多