Execute pending job with ActiveJob in rspec

14,230

Solution 1

Here is how I solved a similar problem:

# rails_helper.rb
RSpec.configure do |config|
  config.before :example, perform_enqueued: true do
    @old_perform_enqueued_jobs = ActiveJob::Base.queue_adapter.perform_enqueued_jobs
    @old_perform_enqueued_at_jobs = ActiveJob::Base.queue_adapter.perform_enqueued_at_jobs
    ActiveJob::Base.queue_adapter.perform_enqueued_jobs = true
    ActiveJob::Base.queue_adapter.perform_enqueued_at_jobs = true
  end

  config.after :example, perform_enqueued: true do
    ActiveJob::Base.queue_adapter.perform_enqueued_jobs = @old_perform_enqueued_jobs
    ActiveJob::Base.queue_adapter.perform_enqueued_at_jobs = @old_perform_enqueued_at_jobs
  end
end

Then in specs we can use:

it "should perform immediately", perform_enqueued: true do
  SomeJob.perform_later  
end

Solution 2

The proper way to test will be to check number of enqueued jobs as in your example, and then test each job separately. If you want to do integration testing you can try perform_enqueued_jobs helper:

describe 'whatever' do
  include ActiveJob::TestHelper

  after do
    clear_enqueued_jobs
  end  

  it 'should email' do
    perform_enqueued_jobs do
      SomeClass.some_action
    end
  end

end

See ActiveJob::TestHelper docs

Share:
14,230

Related videos on Youtube

Olivier
Author by

Olivier

Updated on June 04, 2022

Comments

  • Olivier
    Olivier almost 2 years

    I have this code to test ActiveJob and ActionMailer with Rspec I don't know how really execute all enqueued job

    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
    
  • Chris Peters
    Chris Peters about 9 years
    Can someone show a less contrived example of what this would look like with a mailer that accepts arguments? I can't seem to get this to work with something like OrderMailer.receipt_email(order.id).
  • justingordon
    justingordon about 8 years
    Great answer. I added this to a file in spec/support. Seems that this is 100% necessary for testing email values in integration tests.
  • David Melin
    David Melin almost 6 years
    Make sure you tack on the deliver_now or deliver_later method when testing a mailer and trying to fire the job.
  • cgat
    cgat over 5 years
    Is this really the only way to ensure jobs are performed inline for specific integration tests? It blows my mind that there isn't a simpler way to do this.
  • colemerrick
    colemerrick almost 5 years
    @cgat No - you could place "ActiveJob::Base.queue_adapter.perform_enqueued_jobs = true" in a before block, and your enqueued jobs will have been performed in time for your examples.