Olivier
Olivier

Reputation: 543

Execute pending job with ActiveJob in rspec

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

Upvotes: 29

Views: 20072

Answers (4)

Dorian
Dorian

Reputation: 9085

I have an :inline_jobs helper, where applied to a test it will perform the enqueued jobs and clear the enqueued jobs

module InlineJobHelpers
  def self.included(example_group)
    example_group.around(:each, :inline_jobs) do |example|
      perform_enqueued_jobs do
        example.run
      end
    ensure
      clear_enqueued_jobs
    end
  end
end

RSpec.configure do |config|
  config.include ActiveJob::TestHelper, :inline_jobs
  config.include InlineJobHelpers, :inline_jobs
end

Upvotes: 1

Alex Ponomarev
Alex Ponomarev

Reputation: 945

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

Upvotes: 32

Lev Lukomskyi
Lev Lukomskyi

Reputation: 6667

Just combined all the best pieces, +included sidekiq:

spec/support/perform_jobs.rb:

require 'sidekiq/testing'

RSpec.configure do |config|
  Sidekiq::Testing.fake!

  config.around(:each, perform_jobs: true) do |example|
    Sidekiq::Testing.inline! do
      queue_adapter = ActiveJob::Base.queue_adapter
      old_perform_enqueued_jobs = queue_adapter.perform_enqueued_jobs
      old_perform_enqueued_at_jobs = queue_adapter.perform_enqueued_at_jobs
      queue_adapter.perform_enqueued_jobs = true
      queue_adapter.perform_enqueued_at_jobs = true
      example.run
    ensure
      queue_adapter.perform_enqueued_jobs = old_perform_enqueued_jobs
      queue_adapter.perform_enqueued_at_jobs = old_perform_enqueued_at_jobs
    end
  end

end

spec/some_spec.rb:

it 'works', perform_jobs: true do
  ...
end

Upvotes: 0

timfjord
timfjord

Reputation: 1829

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

Upvotes: 27

Related Questions