【问题标题】:Test ActiveJob retry using instance double使用实例双精度测试 ActiveJob 重试
【发布时间】:2019-06-07 18:51:57
【问题描述】:

我正在尝试使用实例替身测试 ActiveJob 工作人员的重试配置,但它失败了。

我在工作中有这个:

class MyWorker < ApplicationJob
  retry_on MyError, wait: 30.minutes, attempts: 3

  def perform
    raise MyError
  end
end

测试看起来像这样:

  context "retry job" do
    let(:instance) { instance_double(MyWorker) }

    it "retries after 30 minutes" do
      allow(MyWorker).to receive(:new).and_return(instance)
      allow(instance).to receive(:perform_now)

      expect(instance).to receive(:retry_job)
        .with({ priority: nil, queue: nil, wait: 30.minutes.to_i })

      MyWorker.perform_now
    end
  end

此测试中断:

    Failure/Error:
           expect(instance).to receive(:retry_job)
             .with({ priority: nil, queue: nil, wait: 30.minutes.to_i })

           (InstanceDouble(MyWorker) (anonymous)).retry_job({:priority=>nil, :queue=>nil, :wait=>1800})
               expected: 1 time with arguments: ({:priority=>nil, :queue=>nil, :wait=>1800})
               received: 0 times

如果我使用allow_any_instance_of 来测试重试,则测试通过,但我想了解如何使用实例双精度进行测试。

【问题讨论】:

  • 你在测试中引用了很多你没有展示的东西。 apiMyWorker 是什么?
  • 抱歉,更新了代码。我的工人是 ActiveJob 类,其中定义了重试。 api 只是一个类,它会引发retry_on 方法捕获的异常。
  • 所以,你正在存根一堆东西,现在还不清楚实际运行的是什么。比如,api.analyze 在哪里被调用?是在perform_now的体内吗?因为您已经删除了perform_now,所以它实际上不会运行。你知道and_call_original吗?
  • 不要测试第三方代码。您使用的所有 gem 都必须经过测试,我敢打赌 ActiveJob 有重试测试。永远不要那样做,测试第三方的东西不是你的责任。看到这个github.com/rails/rails/blob/master/activejob/test/jobs/…?,他们正在测试这些东西。
  • @fanta 是的,但肯定有人想要测试他们自己的代码调用这个,对吧?自定义类是否启用了重试?

标签: ruby-on-rails ruby rspec rails-activejob


【解决方案1】:
it 'retries the job 3 times with 30 minutes intervals' do
  allow(MyWorker).to receive(:retry_on)
  load 'app/path/to/job/my_worker.rb'
  expect(MyWorker).to have_received(:retry_on)
    .with(
      MyError,
      wait: 30.minutes,
      attempts: 3
    )
end

【讨论】:

    【解决方案2】:

    我不建议以这种方式进行测试,因为它不是在测试所描述的类; doubles 的用例是模拟其他接触您正在测试的描述类的对象的预期行为——而不是描述的类本身。 let(:instance) { instance_double(MyWorker) } 应替换为作业类的真实实例,如下所示:

    subject(:job) { described_class.new }
    

    您可能会发现this gist 以及Rspec's Job Spec documentation 很有帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-11
      • 1970-01-01
      • 2022-11-12
      • 1970-01-01
      • 2021-01-04
      相关资源
      最近更新 更多