How to check what is queued in ActiveJob using Rspec

99封情书 提交于 2019-12-02 17:56:16

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

You really don't need to test ActiveJob functionality. Just test that your code calls it properly by stubbing it out

 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

However if nothing can't stop you of doing a full integration 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

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.

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

There is a new rspec extension which makes your life easier.

require 'rails_helper'

RSpec.describe MyController do
  let(:user) { FactoryGirl.create(:user) }
  let(:params) { { user_id: user.id } }
  subject(:make_request) { described_class.make_request(params) }

  it { expect { make_request }.to enqueue_a(RequestMaker).with(global_id(user)) }
end

I had some problems, maybe because I didn't include ActiveJob::TestHelper, but this worked for me...

Firstly ensure, that you have the queue adapter set to :test as above answers show.

For some reason clear_enqueued_jobs jobs in the after block didn't work for me, but the source shows we can do the following: enqueued_jobs.clear

require 'rails_helper'
include RSpec::Rails::Matchers

RSpec.describe "my_rake_task", type: :rake do

  after do
    ActiveJob::Base.queue_adapter.enqueued_jobs.clear
  end  


  context "when #all task is run" do
    it "enqueues jobs which have been enabled" do
      enabled_count = get_enabled_count
      subject.execute
      expect(ActiveJob::Base.queue_adapter.enqueued_jobs.size).to eq(enabled_count)
    end

    it "doesn't enqueues jobs which have been disabled" do
      enabled_count = get_enabled_count
      subject.execute
      expect(ActiveJob::Base.queue_adapter.enqueued_jobs.size).to eq(enabled_count)
    end
  end

end
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!