RSpec如何测试Sidekiq Job是否在指定时间被调度运行
问题原因&解决方案
- 第一,断言执行顺序错误:你在调用
worker.perform之前就执行了断言,此时任务还没有被入队,自然检测不到。断言必须放在业务代码执行之后。 - 第二,断言参数不匹配:你的Worker中调用
JobBlastingWorker.perform_in时传递了3个参数job.id, 're-blast', true,但测试断言里只写了前2个参数,参数不匹配导致匹配不到已入队的任务。 - 第三,依赖配置缺失:需要在项目中引入
rspec-sidekiqgem,并且测试环境开启Sidekiq的假队列模式,才能正确捕获入队的任务。 - 额外注意:你写的测试文件后缀是
job_blasting_worker_spec.erb,RSpec测试文件的标准后缀是.rb,如果实际文件确实用了.erb后缀会导致RSpec无法正常加载执行该测试。
修正后的测试代码
require 'rails_helper' # 若未在rails_helper中全局配置,需手动引入sidekiq测试工具 require 'sidekiq/testing' describe JobBlastingWorker do before(:all) do Rails.cache.clear end # 测试前清空所有假队列,避免其他用例的任务干扰 before do Sidekiq::Worker.clear_all end describe 'perform' do context 'create' do it 'creates job schedule for next 2mins' do @job = create(:job) worker = JobBlastingWorker.new # 先执行Worker代码,触发任务入队 worker.perform(@job.id, 'create') # 再做断言,补全第三个匹配参数true expect(JobBlastingWorker).to have_enqueued_sidekiq_job(@job.id, 're-blast', true).in(2.minutes) end end end end
可选调试方案
如果需要更直观的验证队列状态,可以在worker.perform执行后添加以下代码打印队列内容,排查参数匹配问题:
puts JobBlastingWorker.jobs.inspect
如果不需要严格校验第三个参数,也可以用泛匹配规则:
expect(JobBlastingWorker).to have_enqueued_sidekiq_job(@job.id, 're-blast', anything).in(2.minutes)
内容的提问来源于stack exchange,提问作者Kingsley Simon
相关产品推荐
相关产品推荐

