【问题标题】:Rspec test retry_onRspec 测试 retry_on
【发布时间】:2021-09-26 19:29:20
【问题描述】:

我有这样的工作

class CrawlSsbHistory < BaseJob
    retry_on(Ssb::SessionExpired) do
      Ssb::Login.call
    end

    def perform
      response = Ssb::Client.get_data
      SsbHistory.last.destroy
    end
  end

我有这样的测试

it "retries the job if session error" do
      allow(Ssb::Client).to receive(:get_data).and_raise(Ssb::SessionExpired)
      allow(Ssb::Login).to receive(:call)
      described_class.perform_now # it is CrawlSsbHistory
      expect(Ssb::Login).to have_received(:call)
    end

CrawlSsbHistory 是一个抓取一些数据的工作。它调用 Ssb::Client.get_data 来获取数据。

如果会话过期,我会在 Ssb::Client.get_data 内部引发 Ssb::SessionExpired。所以我可以使用 retry_on 捕获作业中引发的错误。那么如果发生了我想试试这份工作。

但我遇到了这样的错误

(Ssb::Login (class)).call(*(any args))
           expected: 1 time with any arguments
           received: 0 times with any arguments

作业没有调用 retry_on 吗?还是我测试错了?如何制作 rspec 来测试 retry_on 是否正常工作并调用 Ssb::Login.call?

【问题讨论】:

  • BaseJob ActiveJob::Base ?
  • 是的,它是@LamPhan

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


【解决方案1】:

retry_on 不会在每次重试时立即调用该块。只有当尝试用尽时。否则,它只会重新安排作业。

来自documentation

您还可以传递一个块,如果自定义逻辑的重试尝试失败,则将调用该块,而不是让异常冒泡。该代码块的第一个参数是作业实例,第二个参数是错误实例。

【讨论】:

  • 所以如果我添加 attemp 等于 1,那么作业会立即重试吗?
  • @dedypuji:不,不是马上。默认延迟为 3 秒,IIRC。
【解决方案2】:

我假设您正在测试 ActiveJob,我猜 retry_on 将把作业排入队列而不是立即执行,因此您可以尝试使用 ActiveJob::TestHelper 设置作业队列

你的测试用例应该是:

require 'rails_helper'
RSpec.describe CrawlSsbJob, type: :job do
 include ActiveJob::TestHelper
 before(:all) do
   ActiveJob::Base.queue_adapter = :test
 end

 it "retries the job if session error" do
   allow(Ssb::Client).to receive(:get_data).and_raise(Ssb::SessionExpired)
   expect(Ssb::Login).to receive(:call)
   # enqueue job
   perform_enqueued_jobs {
    described_class.perform_later # or perform_now
   end
 end
end

【讨论】:

    猜你喜欢
    • 2023-03-18
    • 2011-06-09
    • 1970-01-01
    • 1970-01-01
    • 2014-05-18
    • 2011-08-27
    • 2017-05-23
    • 2013-06-17
    • 2019-01-01
    相关资源
    最近更新 更多