Rspec 如何测试 Sidekiq 作业是不是计划在特定时间运行

Posted

技术标签:

【中文标题】Rspec 如何测试 Sidekiq 作业是不是计划在特定时间运行【英文标题】:Rspec How to test if a Sidekiq Job was scheduled to run at a certain timeRspec 如何测试 Sidekiq 作业是否计划在特定时间运行 【发布时间】:2021-11-15 13:31:40 【问题描述】:

我有以下工人

class JobBlastingWorker
  include Sidekiq::Worker
  sidekiq_options queue: 'job_blasting_worker'

  def perform(job_id, action=nil)
    job = Job.find(job_id)

    JobBlastingService.new(job).call
    sidekiq_id = JobBlastingWorker.perform_in(2.minutes, job.id, 're-blast', true)
    job.sidekiq_trackers.create(sidekiq_id: sidekiq_id, worker_type: 'blast_version_update')
  end
end

在我的 rspec 测试中,我有以下 job_blasting_worker_spec.erb

require 'rails_helper'

describe JobBlastingWorker do
  before(:all) do
    Rails.cache.clear
  end

  describe 'perform' do
    context 'create' do
      it 'creates job schedule for next 2mins' do
        @job = create(:job)
        worker = JobBlastingWorker.new
        expect(JobBlastingWorker).to have_enqueued_sidekiq_job(@job.id, 're-blast').in(2.minutes)
        worker.perform(@job.id, 'create')
      end
    end
  end
end

我希望这会起作用,但我意识到应该安排在接下来的 2 分钟内的 sidekiq 作业永远不会被创建。因此,测试失败。

如何确保 sidekiq 作业在接下来的 2 分钟内实际创建并且测试成功运行?

【问题讨论】:

【参考方案1】:

嗯...对于这种期望,我建议只是测试发送给方法的消息。

  expect(JobBlastingWorker).to have_enqueued_sidekiq_job(@job.id, 're-blast')
  expect(JobBlastingWorker).to receive(:perform_in).with(2.minutes, job.id, 're-blast', true).and_call_original
  worker = JobBlastingWorker.new
  worker.perform(@job.id, 'create')

当然,如果你真的很努力,我想你最终会找到一种方法来找到队列中的活动作业对象,例如直接使用 Redis API。 然后您可以进一步检查该对象并获取您为要执行的作业设置的时间。 但为什么? ActiveJob 有责任确保这些作业在正确的时间执行。 发现这一点对您没有多大帮助,并且这种行为应该已经在 RSpec 的测试中进行了测试。 我认为您无需担心,除非它工作不正常并且您想重现这种情况并发出错误。

另一方面,您发送给方法的时间是您应该关心的。您不希望有人意外将其更改为 2.hours。 所以我建议你应该测试你发送给方法的消息。

【讨论】:

以上是关于Rspec 如何测试 Sidekiq 作业是不是计划在特定时间运行的主要内容,如果未能解决你的问题,请参考以下文章

rspec-sidekiq have_enqueued_sidekiq_job未定义的方法at

Rails/Rspec:测试延迟作业邮件

rspec rails testing:如何强制 ActiveJob 作业内联运行某些测试?

Sidekiq 是不是按照发送给工作人员的顺序执行作业?

Rails 6.1:Heroku 上的作业将使用 Async 而不是 Sidekiq

Sidekiq 停止一项正在运行的作业