Skip to content

Instantly share code, notes, and snippets.

@ChuckJHardy
Last active March 3, 2024 20:10
Show Gist options
  • Star 89 You must be signed in to star a gist
  • Fork 25 You must be signed in to fork a gist
  • Save ChuckJHardy/10f54fc567ba3bd4d6f1 to your computer and use it in GitHub Desktop.
Save ChuckJHardy/10f54fc567ba3bd4d6f1 to your computer and use it in GitHub Desktop.
Example ActiveJob with RSpec Tests
class MyJob < ActiveJob::Base
queue_as :urgent
rescue_from(NoResultsError) do
retry_job wait: 5.minutes, queue: :default
end
def perform(*args)
MyService.call(*args)
end
end
require 'rails_helper'
RSpec.describe MyJob, type: :job do
include ActiveJob::TestHelper
subject(:job) { described_class.perform_later(123) }
it 'queues the job' do
expect { job }
.to change(ActiveJob::Base.queue_adapter.enqueued_jobs, :size).by(1)
end
it 'is in urgent queue' do
expect(MyJob.new.queue_name).to eq('urgent')
end
it 'executes perform' do
expect(MyService).to receive(:call).with(123)
perform_enqueued_jobs { job }
end
it 'handles no results error' do
allow(MyService).to receive(:call).and_raise(NoResultsError)
perform_enqueued_jobs do
expect_any_instance_of(MyJob)
.to receive(:retry_job).with(wait: 10.minutes, queue: :default)
job
end
end
after do
clear_enqueued_jobs
clear_performed_jobs
end
end
# As of RSpec 3.4.0 we now have #have_enqueued_job
# https://www.relishapp.com/rspec/rspec-rails/v/3-5/docs/matchers/have-enqueued-job-matcher
RSpec.describe MyJob, type: :job do
subject(:job) { described_class.perform_later(key) }
let(:key) { 123 }
it 'queues the job' do
expect { job }.to have_enqueued_job(described_class)
.with(key)
.on_queue("urgent")
end
end
@kaka-ruto
Copy link

๐Ÿ‘

@gogvale
Copy link

gogvale commented Sep 7, 2021

๐Ÿ‘

@Proxima89
Copy link

๐Ÿ‘

@mandarvaze
Copy link

Is there a way to test that retry happened after :wait period ?

@ChuckJHardy
Copy link
Author

Is there a way to test that retry happened after :wait period ?

Great question @mandarvaze! This feels like testing the internals of Rails, which I avoid to ensure I can move confidently without brittle tests. I am happy to trust that if the expected arguments are passed during the method call, the framework is doing its job as expected. If testing this is critical to your flow, maybe high-level acceptance tests are better suited. Hope this helps.

@mandarvaze
Copy link

@ChuckJHardy Thanks. It does make sense to trust the internals ๐Ÿ˜„

@chumakoff
Copy link

chumakoff commented Feb 16, 2024

subject(:job) { described_class.perform_later(123) }

it 'queues the job' 

it 'executes perform' 

Those two specs don't test your job. They test the ActiveJob's #perform_later method, wich is pointless.

This kind of test shouldn't use the perform_enqueued_jobs method at all. It's for higher level tests.

@lortza
Copy link

lortza commented Feb 26, 2024

๐Ÿ‘

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment