2014-10-26 186 views
21

我的應用程序中有一些複雜的,長時間運行的delayed_job進程。我正在使用Rspec來測試流程中使用的各個方法和類,但我還想使用不同的測試數據執行許多端到端的後臺作業。Rspec測試delayed_job

我在delayed_job wiki上找不到任何東西,這個問題看起來很有趣,但我並不真正瞭解這裏發生了什麼。 What's the best way to test delayed_job chains with rSpec?

我可以很容易地用工廠設置測試數據,然後調用開始後臺處理的類。我預計測試需要很長時間才能完成。

編輯後臺代碼

class Singleplex 
    def perform(batch_id,user) 
     batch = start_batch(batch_id,user) 
     ... do lots of stuff ... 
    end 
    handle_asynchronously :perform, queue: :singleplex, :run_at => Proc.new { 1.second.from_now } 

規格/工廠/ batches.rb

FactoryGirl.define do 
    factory :batch do 
    batch_type 'singleplex' 
    name 'valid panel' 
    status 'ready' 
    end 

    factory :batch_detail do 
    chrom 7 
    chrom_start 140435012 
    chrom_end 140435012 
    target_offset 150 
    padding 4 
    primer3_parameter_id 1 
    snp_mask 't' 
    status 'ready' 
    batch 
    end 
end 

然後像這樣運行

describe Batch do 
    it 'runs Singleplex for a valid panel' do 
    batch = FactoryGirl.create(:batch) 
    user = User.find(1) 
    status = Singleplex.new.perform(batch.id,user) 
    expect(status.should == true) 
    end 
end 

測試我有兩個問題需要解決:

1)在驗證結果之前如何告訴測試等待delayed_job調用完成?

2)爲了驗證結果,我需要檢查多個表中的值。在Rspec中做這件事的最好方法是什麼?

編輯

我要補充,我收到了delayed_job的對象,所以理所當然的狀態檢查失敗。這些工作通常至少需要10分鐘。

1) Batch runs Singleplex for a valid panel 
    Failure/Error: expect(status.should == true) 
     expected: true 
      got: #<Delayed::Backend::ActiveRecord::Job id: nil, priority: 0, attempts: 0, handler: "--- !ruby/object:Delayed::PerformableMethod\nobject:...", last_error: nil, run_at: nil, locked_at: nil, failed_at: nil, locked_by: nil, queue: nil, created_at: nil, updated_at: nil> (using ==) 
+2

順便說一句,它看起來像你混的RSpec的'should'和'expect'語法。 'expect(status.should == true)'應該是'status.should == true'或'expect(status).to == true' – fny 2014-11-03 19:55:20

回答

31

有幾種方法可以做到這一點。他們都需要你在你的代碼中執行這項工作。方法1:測試將作業排隊,然後告知DelayedJob::Worker完成該作業。方法2:運行有關作業並禁用排隊功能並檢查所需結果的測試。您可以通過在您的測試配置或before塊中的某處調用Delayed::Worker.delay_jobs = false來延遲排隊。

before(:each) do 
    Delayed::Worker.delay_jobs = false 
end 
describe Batch do 
    it 'runs Singleplex for a valid panel' do 
    batch = FactoryGirl.create(:batch) 
    user = User.find(1) 
    Singleplex.new.perform(batch.id,user) 
    # expectations which check that the work is done 
    end 
end 

然而,該方法已被cause issues with callbacks所知曉。方法3:編寫一個觀察者,監視創建並運行它們的任何新作業。這樣您就不必在測試中手動聲明「work_off」。 Artsy有gist for this

這也是一個不錯的主意,有測試其他地方確保工作得到排隊預期

it "queues welcome when a user is created" do 
    expect(Delayed::Job.count).to eq 0 
    # Create user step 
    expect(Delayed::Job.count).to eq 1 # You should really be looking for the count of a specific job. 
end 
+0

感謝@faraz,對於方法3,您是在哪裏添加引用'delayed_job_observer.rb',它在'spec_helper.rb'中嗎? – Dean 2015-03-06 08:34:48

+0

如果您使用較新的組織格式,請使用'rails_helper.rb',否則使用'spec_helper.rb'。 – fny 2015-03-06 14:20:22

+0

在你的第一個方法中,不應該馬上執行這個工作,它不會排隊嗎? – jshah 2017-12-06 22:26:48

5

如果要奔波單個測試或一組測試推遲的工作,你可以將它添加到您的spec_helper。RB

config.around(:each, :run_delayed_jobs) do |example| 
    Delayed::Worker.delay_jobs = false 

    example.run 

    Delayed::Worker.delay_jobs = true 
end 

裏調用:

it 'runs the job', :run_delayed_jobs do 
    # delayed job magic 
end