如何编写RSpec测试验证Sidekiq Worker异步调用的传入参数是否正确
你的测试存在三个核心问题
- 重复声明
ScoringWorker.perform_async的期望:第二次无参数匹配的expect(ScoringWorker).to receive(:perform_async).exactly(1).times会覆盖第一次带参数校验的期望,导致参数校验逻辑失效,触发参数不匹配报错 - 多余的
JobBlastingWorker.perform_in期望:你的现有业务代码中没有任何调用perform_in的逻辑,这条无厘头的期望会直接触发测试失败 - 不需要加
and_call_original:如果你只是要验证参数是否正确,不需要真的执行ScoringWorker的逻辑,加了反而可能引入额外的数据库操作等依赖
正确的测试写法
写法1:使用rspec-sidekiq gem(推荐,语法更简洁)
首先确保你在Gemfile的test组里添加了rspec-sidekiq依赖,测试代码如下:
require 'rails_helper' RSpec.describe JobBlastingWorker do describe '#perform' do context 'when action is create' do it 'triggers ScoringWorker with correct parameters' do job = create(:job) # 执行worker逻辑 described_class.new.perform(job.id, 'create') # 验证ScoringWorker的入参符合预期 expect(ScoringWorker).to have_enqueued_sidekiq_job(job.id, 0, 'create').exactly(1).times end end end end
写法2:手动mock(不需要额外依赖)
require 'rails_helper' RSpec.describe JobBlastingWorker do describe '#perform' do context 'when action is create' do it 'triggers ScoringWorker with correct parameters' do job = create(:job) # 只声明一次带参数校验的期望即可 expect(ScoringWorker).to receive(:perform_async).with(job.id, 0, 'create').exactly(1).times # 执行worker逻辑 described_class.new.perform(job.id, 'create') end end end end
额外注意事项
如果需要真的执行异步任务的逻辑做集成测试,可以打开Sidekiq的测试内联模式:
Sidekiq::Testing.inline! do described_class.new.perform(job.id, 'create') end
这种模式下所有异步任务会同步执行,你可以额外验证后续的业务逻辑(比如job的version是否被正确更新为0)。
内容的提问来源于stack exchange,提问作者Kingsley Simon
相关产品推荐
相关产品推荐

