2011-06-15 25 views
21

Solo me preguntaba cómo probar que las solicitudes de Actionmailer se envían realmente a la cola delayed_job en rspec.Rails/Rspec: Probar correos de retraso_trabajo

Hubiera supuesto que era bastante simple, pero mi cola de retraso de la tarea no parece estar aumentando. Código de abajo:

controlador:

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 

Spec:

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 

Tanto antes como después de la llamada al controlador, el Retraso :: Job.count devuelve 0. He intentado tomar el condicional fuera del controlador, pero todavía no puedo obtener el recuento de trabajo retrasado para incrementar.

Cualquier sugerencia apreciados - alegría

Respuesta

45

También puede probar qué harán los trabajos ejecutándolos o apagando las colas.

Ajuste la configuración siempre que lo desee (es decir, en un bloque before :each).

Delayed::Worker.delay_jobs = false 

o realizar sus trabajos guardados

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

que han estado utilizando este método felices durante un tiempo. Por un lado, utilizando el nuevo soporte any_instance en RSpec, puede probar sus efectos de métodos retrasados ​​directamente. Sin embargo, he encontrado pruebas que usan work_off para ser lento.

Lo que suelo hacer ahora es:

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

entonces tengo una especificación separada para my_delayed_method. Esto es mucho más rápido, y probablemente sea una mejor práctica de pruebas unitarias, particularmente para los controladores. Aunque si está solicitando especificaciones de solicitud u otras especificaciones de nivel de integración, entonces probablemente todavía desee utilizar work_off.

+0

me gusta de esta manera. Tenga en cuenta que, para completar, también debería (por separado) probar que los trabajos retrasados ​​se están agregando a la tabla delayed_jobs. – brittohalloran

+1

Esto es resbaladizo, ¡gracias! – jpwynn

16

Creo que su objeto de burla de alguna manera está introduciendo un error - es difícil decir exactamente cómo sin ver la definición del método mock_contact.

En cualquier caso, puede intentar algo como lo siguiente:

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 

o la versión más atractivo (advertencia: siempre termino haciéndolo de la forma no atractiva):

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

También puede seguir la convención (de Railscast 275) de

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

pero en vez de hacer esto:

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

Este hilo es un poco viejo, pero aquí es mi ir en él:

Crear una función expect_jobs

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 

Luego simplemente llámalo antes de verificar si la devolución de llamada ha hecho su trabajo. por ejemplo:

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 

Esto parece funcionar en mi lado, y me permite ejecutar mis dos trabajos retrasados ​​ y mis métodos.

1

@zetetic Creo que tenemos que pasar el bloque en el método de cambio aquí.

Se shoulb ser así:

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 
Cuestiones relacionadas