测试:如何检查一个 sidekiq 作业是否将另一个 sidekiq 作业排入队列

Tests: How to check if a sidekiq job enqueued another sidekiq job

提问人:Felipe Junges 提问时间:10/8/2023 更新时间:10/8/2023 访问量:39

问:

我有这两个示例类,我想编写一个首次运行 PaymentCheckJob 的 rspec,如果payment_type == 'ticket',我想检查它是否将另一个 sidekiq 作业排入队列

class ApplicationJob
  include Sidekiq::Job
  sidekiq_options retry: 1

  def perform(*args)
    # Do something
  end
end

class PaymentCheckJob < ApplicationJob
  def perform(args = '{}')
    args = JSON.parse(args)
    invoice_id = args['invoice_id']
    if invoice.payment_type == 'ticket'
      ::PaymentCheckJob.perform_at(1.hour.from_now, { 'invoice_id': invoice.id }.to_json)
      # ::PaymentCheckJob.perform_in(3600, { 'invoice_id': invoice.id }.to_json)
    else
      invoice.payed_at = Time.now
    end
  end
end
Ruby-on-Rails rspec-sidekiq

评论


答:

0赞 mechnicov 10/8/2023 #1

您可以存根此方法,编写两个不同的上下文:当作业排队时和未排队时

像这样的东西

require 'rails_helper'

RSpec.describe PaymentCheckJob, type: :job do
  describe '#perform' do
    subject(:perform_job) { described_class.new.perform(invoice_id: invoice.id) }

    let(:invoice) { Invoice.create(payment_type: payment_type) }

    before { allow(described_class).to receive(:perform_at) }

    context 'when invoice is ticket' do
      let(:payment_type) { 'ticket' }

      it 'enqueues another PaymentCheckJob' do
        perform_job

        expect(described_class).to have_received(:perform_at)
      end
    end

    context 'when invoice is not ticket' do
      let(:payment_type) { 'not_ticket' }

      it 'does not enqueue another PaymentCheckJob' do
        perform_job

        expect(described_class).not_to have_received(:perform_at)
      end
    end
  end
end

您还可以检查作业大小,例如

expect { perform_job }.to change { PaymentCheckJob.jobs.size }.by(1)
expect { perform_job }.not_to change { PaymentCheckJob.jobs.size }

您还可以在文档中阅读有关测试 Sidekiq 的提示


但我不确定从另一个作业调用一个作业是个好主意。也许你可以用 cron 安排这个作业(例如每 5 分钟 1 个),而不是传递一些参数,而是在作业主体内获取这些发票的批次(例如一些范围,如 )。要排除争用条件,您可以锁定这些发票以进行更新。此外,为了确保没有两个作业同时运行,请使用咨询锁定 (mutex) 锁定 perform 方法的正文。当然,如果需要,还可以更新发票。在这种情况下,您将更多地管理流程,并且作业不会以某种方式相互调用。我认为如此Invoice.not_processed