【发布时间】:2022-01-03 09:39:03
【问题描述】:
我一直在用instance_doubles 编写测试,以在我需要在链中更细化时代替消息链。但是,我想知道我是否正在努力地做事。
这是我要测试的方法:
def run_produceable_job
# Delete any jobs that exist, but haven't started, in favor of this new job
Delayed::Job.where(queue: 'produceable', locked_at: nil).delete_all
ProduceableJob.perform_later
end
对于Delayed::Job 调用,重要的是我检查队列名称是否符合预期。
我还想确保 Delayed::Job 最后收到.delete_all
我想做这样的事情:
expect(Delayed::Job).to receive(:where).with(queue: 'produceable', locked_at: nil).and_then_receive(:delete_all)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
RSpec 是否为接收提供某种链接? 我浏览了文档,但找不到任何专门讨论添加多个接收的内容。
还是我必须走很长的路?
ar_relation = instance_double ActiveRecord::Relation
allow(Delayed::Job).to receive(:where).with(queue: 'produceable', locked_at: nil).and_return(ar_relation)
allow(ar_relation).to receive(:delete_all)
expect(Delayed::Job).to receive(:where).with(queue: 'produceable', locked_at: nil)
expect(ar_relation).to receive(:delete_all)
【问题讨论】:
-
恕我直言,您必须走很长的路。无论如何,我建议您过度考虑您的测试策略。目前,您测试是否调用了非常特定的方法组合,但如果这些方法调用实际上正在执行您想要的操作,则不会。相反,我将创建一个应该删除的示例记录(可能还有一些不应该删除的记录),然后运行该作业,然后测试是否只删除了预期的记录。经验法则是测试预期的结果,而不是具体的实现,因为在未来的版本中实现可能会发生变化或中断。
-
^ 编写测试的一个主要原因是它为我们提供了重构代码的安全性。但是,如果您的测试强制执行特定的实现,那么它对于重构目的就变得毫无价值——更改代码意味着破坏测试。
-
@spickermann 你应该添加这个作为答案:)
标签: ruby-on-rails ruby rspec rspec-expectations