RSpec: 如何链接 receive().with()?
RSpec: how to chain receive().with()?
我一直在用 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)
恕我直言,你必须走很长的路。没有更短的方式来描述它。
无论如何,我建议您考虑一下您的测试策略。目前,您正在测试是否调用了非常具体的方法组合,但如果这些方法调用实际上正在执行您希望它们执行的操作,则不会。
相反,我会创建一个应该删除的示例记录(也许还有一对不应该删除的记录),然后 运行 作业,然后测试是否只删除了预期的记录。
例如像这样:
let!(:record_to_be_deleted) {
Delayed::Job.create!(queue: 'produceable', locked_at: nil)
}
let!(:records_to_stay) do
[
Delayed::Job.create!(queue: 'produceable', locked_at: Time.current),
Delayed::Job.create!(queue: 'default', locked_at: nil)
]
end
it "should remove only expected records" do
expect {
instance.run_produceable_job
}.to chance { Delayed::Job.count }.from(3).to(2)
expect {
record_to_be_deleted.reload
}.to raise_error(ActiveRecord::RecordNotFound)
end
经验法则是测试预期的结果,而不是具体的实施。因为实现可能会改变,将在未来的版本中重构或可能会中断。
我一直在用 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)
恕我直言,你必须走很长的路。没有更短的方式来描述它。
无论如何,我建议您考虑一下您的测试策略。目前,您正在测试是否调用了非常具体的方法组合,但如果这些方法调用实际上正在执行您希望它们执行的操作,则不会。
相反,我会创建一个应该删除的示例记录(也许还有一对不应该删除的记录),然后 运行 作业,然后测试是否只删除了预期的记录。
例如像这样:
let!(:record_to_be_deleted) {
Delayed::Job.create!(queue: 'produceable', locked_at: nil)
}
let!(:records_to_stay) do
[
Delayed::Job.create!(queue: 'produceable', locked_at: Time.current),
Delayed::Job.create!(queue: 'default', locked_at: nil)
]
end
it "should remove only expected records" do
expect {
instance.run_produceable_job
}.to chance { Delayed::Job.count }.from(3).to(2)
expect {
record_to_be_deleted.reload
}.to raise_error(ActiveRecord::RecordNotFound)
end
经验法则是测试预期的结果,而不是具体的实施。因为实现可能会改变,将在未来的版本中重构或可能会中断。