How to check what is queued in ActiveJob using Rspec

Rspec 3.4 now has have_enqueued_job cooked in, which makes this a lot easier to test:

it "enqueues a YourJob" do
  expect {
    get :your_action, {}
  }.to have_enqueued_job(YourJob)
end

it has other niceties for have_enqueued_job to allow you to check the argument(s) and the number of times it should be queued up.


The accepted answer no longer works for me, so I tried Michael H.'s suggestion in the comments, which works.

describe 'whatever' do
  include ActiveJob::TestHelper

  after do
    clear_enqueued_jobs
  end  

  it 'should email' do
    expect(enqueued_jobs.size).to eq(1)
  end
end

Testing Rails ActiveJob with RSpec

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

In a unit test, instead of checking what is queued one can also rely on ActiveJob working properly and just verify that it will be called by mocking its api.

 expect(MyJob).to receive(:perform_later).once 
 post :reset_password, user: { email: user.email }

The creators of the ActiveJob have used the same techniques for their unit tests. See GridJob Testobject

They create a testmock GridJob in their tests and override the perform method, so that it only adds jobs to a custom Array, they call JobBuffer. At the end they test, whether the buffer has jobs enqueued

At a single place one can ofc also do an integrations test. The ActiveJob test_helper.rb is supposed to be used with minitest not with rspec. So you have to rebuild it's functionalitity. You can just call

expect(ActiveJob::Base.queue_adapter.enqueued_jobs).to eq 1

without requiring anything

Update 1: As noticed within a comment. ActiveJob::Base.queue_adapter.enqueued_jobs works only by setting it the queue_adapter into test mode.

# either within config/environment/test.rb
config.active_job.queue_adapter = :test

# or within a test setup
ActiveJob::Base.queue_adapter = :test