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

问题描述 投票:0回答:1

我有这两个示例类,我想编写一个第一次运行 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 rspec-rails sidekiq rspec-sidekiq
1个回答
0
投票

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

类似这样的事情

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 }

但我不确定从一项工作调用另一项工作是个好主意。也许您可以使用 cron 安排此作业(例如每 5 分钟 1 次),而不是传递一些参数,而是在作业主体内获取一批这些发票(例如像

Invoice.not_processed
这样的范围)。要排除竞争条件,您可以锁定这些发票以进行更新。另外,为了确保没有两个作业同时运行,请使用建议锁定(互斥锁)锁定执行方法的主体。当然,如果需要的话还可以更新发票。在这种情况下,您将更多地管理流程,并且作业不会以某种方式混乱地相互调用。我也这么认为

© www.soinside.com 2019 - 2024. All rights reserved.