2014-10-09 12 views
28

我正在研究Rails API應用程序中的reset_password方法。當這個端點被擊中時,一個ActiveJob被排隊,將發出一個請求到Mandrill(我們的交易電子郵件客戶端)。我正在嘗試編寫測試以確保在控制器端點被擊中時ActiveJob已正確排隊。如何使用Rspec檢查在ActiveJob中排隊的內容

def reset_password 
    @user = User.find_by(email: params[:user][:email]) 
    @user.send_reset_password_instructions 
end 

的send_reset_password_instructions創建它的代碼ActiveJob之前產生了一些網址等低於:

class SendEmailJob < ActiveJob::Base 
    queue_as :default 

    def perform(message) 
    mandrill = Mandrill::API.new 
    mandrill.messages.send_template "reset-password", [], message 
    rescue Mandrill::Error => e 
    puts "A mandrill error occurred: #{e.class} - #{e.message}" 
    raise 
    end 
end 

在我們沒有使用的ActiveJob任何適配器的時刻,所以我只是想檢查使用RSpec ActiveJob已排隊。

目前我的測試看起來是這樣的(我使用工廠女孩創建用戶):

require 'active_job/test_helper' 

describe '#reset_password' do 
    let(:user) { create :user } 

    it 'should create an ActiveJob to send the reset password email' do 
    expect(enqueued_jobs.size).to eq 0 
    post :reset_password, user: { email: user.email } 
    expect(enqueued_jobs.size).to eq 1 
    end 
end 

一切都在現實的作品,我只需要創建測試!

我使用的是ruby 2.1.2和rails 4.1.6。

我看不到任何文檔或幫助網絡上的任何地方如何測試這個,所以任何幫助將不勝感激!

回答

35

接受的答案不再爲我工作,所以我試圖在評論中,其工作邁克爾·H的建議。

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 
+0

謝謝,這是一個很大的幫助。是有什麼方法可以檢查正確的作業排隊? – bobomoreno 2014-12-25 13:24:24

+0

這應該是公認的答案。 – 2015-01-19 10:59:33

+7

「ActiveJob :: TestHelper」ist旨在與minitest不使用rspec一起使用。它的代碼充滿了'assert_equal'等。只包含一個方法是壞主意,恕我直言。該模塊內的方法'enqueued_jobs'僅僅是'ActiveJob :: Base.queue_adapter.enqueued_jobs' – 2015-02-09 22:12:21

33

你真的不需要測試ActiveJob功能。只是測試你的代碼通過測試框架出來

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

的ActiveJob的創建者已經使用了他們的單元測試相同的技術稱之爲正常。請參閱GridJob Testobject

他們在其測試中創建testmock GridJob並重寫執行方法,以便它僅將作業添加到自定義數組,他們將其稱爲JobBuffer。最後,他們測試,緩衝區是否有作業入隊

但是,如果沒有什麼能阻止您進行完整的集成測試。 ActiveJob test_helper.rb應該與minitest一起使用,而不是rspec。所以你必須重建它的功能性。你可以叫

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

,而不需要任何

更新1: 作爲一個註釋中注意到。 ActiveJob::Base.queue_adapter.enqueued_jobs只適用於將queue_adapter設置爲測試模式。

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

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

所以最後我做你的第一個建議。該ActiveJob test_helper不使用RSpec煩人 – mylescc 2014-10-10 13:41:21

+1

@mylescc我能得到test_helper將其包含在我的Rspec.describe塊工作的工作:'包括ActiveJob :: TestHelper' – 2014-10-13 16:47:48

+0

不知道還是沒有爲我工作。我試過包括內部描述,也試過在配置塊中。 – 2014-11-05 17:01:39

8

有一個新的rspec extension這讓你的生活更輕鬆。

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 
8

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 
12

Rspec 3.4現在有have_enqueued_job熟,這使得更容易測試這個有很多:

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

它有其他細微的have_enqueued_job允許你檢查參數和應該排隊的次數。

+2

誰發現這很有用,我用'期待{}。要have_enqueued_job.on_queue(「郵寄」)'檢查發送的電子郵件。 – 2016-06-29 03:59:41

0

我遇到了一些問題,也許是因爲我不包括ActiveJob :: TestHelper,但這個工作對我來說...

首先保證,您擁有的隊列適配器設置爲:test如上答案顯示。

出於某種原因clear_enqueued_jobs工作在after塊並沒有爲我工作,但source顯示了我們可以做到以下幾點: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 
相關問題