I have this two example class, and I want to write a rspec that runs PaymentCheckJob for first time, and if payment_type == 'ticket', I want to check if it enqueued another sidekiq job
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
You can stub this method, write two different contexts: when job is enqueued and when not
Something like this
You can also check jobs size like
You can also read hints about testing of Sidekiq in the docs
But I don't sure it's good idea to invoke one job from another. Probably you can schedule this job with cron (for example 1 per 5 minutes) and instead of passing some arguments fetch batch of these invoices (for example some scope like
Invoice.not_processed) inside the job body. To exclude race condition you can lock these invoices for update. Also to ensure no two jobs run at the same time lock body of perform method with advisory locking (mutex). And of course update invoices if needed. In this case, you will be more in managing the processes, and jobs will not somehow messy invoke each other. I think so