2011-06-15 8 views
21

실제로 actionmailer 요청을 테스트하는 방법에 대해 궁금한 점은 실제로 rspec의 delayed_job que로 전송됩니다.Rails/Rspec : delayed_job 메일 테스트

나는 꽤 간단하다고 생각했지만, delayed_job 큐는 증가하지 않는 것 같습니다. 아래 코드 :

컨트롤러 :

def create 
    @contact = Contact.new(params[:contact]) 
     if @contact.save 
     contactmailer = ContactMailer 
     contactmailer.delay.contact_message(@contact) 
     redirect_to(contacts_url) 
     else 
     render :action => "new" 
     end 

사양 :

it "queues mail when a contact is created" do 
    expectedcount = Delayed::Job.count + 1 
    Contact.stub(:new).with(mock_contact()) { mock_contact(:save => true) } 
    post :create, :contact => mock_contact 
    expectedcount.should eq(Delayed::Job.count) 
    end 

전에 컨트롤러에 대한 호출 후 두, 지연된 :: Job.count 내가 복용 해봤 0을 반환 조건부 컨트롤러에서,하지만 난 여전히 증가 지연 작업 수를 얻을 수 없습니다. 감사

어떤 제안 - 응원

답변

45

대기열을 실행하거나 대기열을 끄면 작업이 수행 할 작업을 테스트 할 수도 있습니다.

필요할 때마다 (예 : before :each 블록) 구성을 조정할 수 있습니다.

Delayed::Worker.delay_jobs = false 

또는 수행 저장된 작업

Delayed::Worker.new.work_off.should == [1, 0] 

나는 잠시 동안 행복이 방법을 사용하고있다. RSpec에서 새로운 any_instance 지원을 사용하여 지연 메소드 효과를 직접 테스트 할 수 있습니다. 그러나 work_off을 으로 사용하는 테스트를 발견했습니다.

은 내가 일반적으로 지금 할 것은 :

mock_delay = double('mock_delay').as_null_object 
MyClass.any_instance.stub(:delay).and_return(mock_delay) 
mock_delay.should_receive(:my_delayed_method) 

가 그럼 난 my_delayed_method에 대해 별도의 사양을 가지고있다. 이것은 훨씬 빠르고, 아마도 더 나은 유닛 테스트 실습입니다. 특히 컨트롤러의 경우 더욱 그렇습니다. 요청 사양 또는 기타 통합 수준 사양을 수행하는 경우에도 여전히 work_off을 사용하려고합니다.

+0

나는이 방법을 좋아한다. 완전성을 위해 지연된 작업이 delayed_jobs 테이블에 추가되는 것을 (별도로) 테스트해야합니다. – brittohalloran

+1

이것은 매끄러운입니다 - 감사합니다! – jpwynn

16

나는 당신의 모의 객체가 어떻게 든 오류를 소개하고있다 생각 - 그것은 mock_contact 방법의 정의를 보지 않고 방법을 정확하게 말할 어렵다. 어떤 경우

, 당신은이 라인을 따라 뭔가 시도 할 수 있습니다 :

it "queues mail when a contact is created" do 
    Contact.stub(:new) { mock_model(Contact,:save => true) } 
    Delayed::Job.count.should == 0 
    post :create, {} 
    Delayed::Job.count.should == 1 
    end 

또는 섹시 버전 (주의 : 난 항상 그것을 비 섹시한 방법 일을 끝낼) :

it "queues mail when a contact is created" do 
    Contact.stub(:new) { mock_model(Contact,:save => true) } 
    expect { 
     post :create, {} 
    }.to change(Delayed::Job.count).by(1) 
    end 
8

또한

ActionMailer::Base.deliveries.last.to.should == user.email 

의 (Railscast 275에서) 협약에 따라 대신 할 수있는이 :

Delayed::Job.last.handler.should have_content(user.email) 
0

이 스레드는 조금 오래지만, 여기에 내 이동이다

함수를 만들기

def expect_jobs n, time = nil 
    expect(Delayed::Job.count).to eq(n) 
    Timecop.travel(time) unless time.nil? 
    successes, failures = Delayed::Worker.new.work_off 
    expect(successes).to eq(n) 
    expect(failures).to eq(0) 
    expect(Delayed::Job.count).to eq(0) 
    Timecop.travel(Time.now) unless time.nil? 
end 
를 expect_jobs

그런 다음 콜백이 해당 작업을 완료했는지 확인하기 전에 간단히 호출하십시오. 예를 들면 :

it "sends a chapter to the admin user" do 
    post :chapter_to_user, { chapter: @book.chapters.first} 
    expect_jobs(1) 
    SubscribeMailer.should have(1).delivery 
    SubscribeMailer.deliveries.should have(1).attachment 
end 

이 내 옆에 작동하는 것, 그리고 내 지연 작업 내 방법을 모두 실행할 수 있습니다.

1

@ zetetic 여기에서 변경 방법을 차단해야한다고 생각합니다.

이 이렇게 될 shoulb :

it "queues mail when a contact is created" do 
Contact.stub(:new) { mock_model(Contact,:save => true) } 
expect { 
    post :create, {} 
    }.to change { Delayed::Job.count }.by(1) 
end 
관련 문제