【发布时间】:2023-03-18 18:56:01
【问题描述】:
过去几天我一直在尝试测试这种方法,但没有成功。
我想做的另一件事是rescue 在进行最后一次重试后冒泡的错误。
请看下面我的 cmets 和代码 sn-ps。
Source code for retry_on is here as well for context.
这是示例代码和测试:
my_job.rb
retry_on Exception, wait: 2.hours, attempts: 3 do |job, exception|
# some kind of rescue here after job.exceptions == 3
# then notify Bugsnag of failed final attempt.
end
def perform(an_object)
an_object.does_something
end
my_spec.rb
it 'receives retry_on 3 times' do
perform_enqueued_jobs do
expect(AnObject).to receive(:does_something).and_raise { Exception }.exactly(3).times
expect(MyJob).to receive(:retry_on).with(wait: 2.hours, attempts: 3).exactly(3).times
MyJob.perform_later(an_object)
end
assert_performed_jobs 3
end
测试失败响应:
1) MyJob.perform receives retry_on 3 times
Failure/Error: expect(job).to receive(:retry_on).with(wait: 4.hours, attempts: 3).exactly(3).times
(MyJob (class)).retry_on({:wait=>2 hours, :attempts=>3})
expected: 3 times with arguments: ({:wait=>2 hours, :attempts=>3})
received: 0 times
# ./spec/jobs/my_job_spec.rb:38:in `block (4 levels) in <top (required)>'
# ./spec/rails_helper.rb:48:in `block (3 levels) in <top (required)>'
# ./spec/rails_helper.rb:47:in `block (2 levels) in <top (required)>'
我也尝试过使工作成为双重并存根 retry_on 方法,但这也不起作用。
我也尝试过使用 Timecop 快进等待时间,但测试仍然失败:
my_spec.rb
it 'receives retry_on 3 times' do
perform_enqueued_jobs do
expect(AnObject).to receive(:does_something).and_raise { Exception }.exactly(3).times
Timecop.freeze(Time.now + 8.hours) do
expect(MyJob).to receive(:retry_on).with(wait: 2.hours, attempts: 3).exactly(3).times
end
MyJob.perform_later(an_object)
end
assert_performed_jobs 3
end
这是ActiveJob 的类方法,我已经在byebug 终端中确认了我的工作类就是这种情况。
这个测试不应该工作吗?它期望类接收带有某些参数的类方法。当我将 byebug 放入 retry_on 块时,我的 byebug 也会被命中,因此我知道该方法被多次调用。
这几乎就像是在另一个班级被调用,这非常令人困惑,我不认为是这种情况,但我已经走到了尽头。
我几乎解决了这个问题,将我的测试从测试retry_on rails 逻辑本身解耦到围绕它测试我的业务逻辑。这种方式在 Rails 改变 retry_on 逻辑的情况下也更好。
但是,这不适用于多个测试用例。如果您在多个案例中使用它,最后一个测试将中断,并说它执行的工作比预期的要多。
my_spec.rb
it 'receives retry_on 3 times' do
perform_enqueued_jobs do
allow(AnObject).to receive(:does_something).and_raise { Exception }
expect(AnObject).to receive(:does_something).exactly(3).times
expect(Bugsnag).to receive(:notify).with(Exception).once
MyJob.perform_later(an_object)
end
assert_performed_jobs 3
end
my_job.rb
retry_on Exception, wait: , attempts: 3 do |job, exception|
Bugsnag.notify(exception)
end
def perform(an_object)
an_object.does_something
end
对此的任何帮助/见解将不胜感激。
也希望获得有关如何在最大尝试次数后处理冒泡异常的建议。我正在考虑在retry_on 块中引发错误,然后让discard_on 触发引发的错误。
感谢精彩的 Stack Overflow 社区!
【问题讨论】:
-
您似乎正在尝试测试
attempts参数是否正常工作,对其进行代码和测试已经是rails框架的一部分。您无需测试它是您的域逻辑的重要组成部分
标签: ruby-on-rails rspec rspec-rails ruby-on-rails-5.1 rails-activejob