ruby-on-rails - tutorial - rspec with rails
Cómo comprobar qué está en cola en ActiveJob usando Rspec (6)
Hay una nueva extensión rspec que hace su vida más fácil.
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
Estoy trabajando en un método reset_password en una aplicación Rails API. Cuando se llega a este punto final, se pone en cola un ActiveJob que activará una solicitud a Mandrill (nuestro cliente de correo electrónico transaccional). Actualmente estoy intentando escribir las pruebas para garantizar que el ActiveJob esté en cola correctamente cuando se golpea el punto final del controlador.
def reset_password
@user = User.find_by(email: params[:user][:email])
@user.send_reset_password_instructions
end
El send_reset_password_instructions crea algunas url, etc. antes de crear el ActiveJob cuyo código está debajo:
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
Por el momento, no estamos usando ningún adaptador para ActiveJob, por lo que solo quiero verificar con Rspec que ActiveJob está en cola.
Actualmente mi prueba se ve más o menos así (estoy usando chica de fábrica para crear el usuario):
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
¡Todo funciona en realidad, solo necesito crear las pruebas!
Estoy usando ruby 2.1.2 y rieles 4.1.6.
No veo ninguna documentación ni ayuda en ningún lugar de la web sobre cómo probar esto, por lo que cualquier ayuda sería muy apreciada.
La respuesta aceptada ya no me funciona, así que probé la sugerencia de Michael H. en los comentarios, que funciona.
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
Realmente no necesita probar la funcionalidad de ActiveJob. Solo prueba que tu código lo llame apropiadamente apagándolo
expect(MyJob).to receive(:perform_later).once
post :reset_password, user: { email: user.email }
Los creadores de ActiveJob han usado las mismas técnicas para sus pruebas unitarias. Ver GridJob Testobject
Crean un GridJob de prueba en sus pruebas y anulan el método de ejecución, por lo que solo agrega trabajos a una matriz personalizada, ellos llaman a JobBuffer . Al final prueban si el buffer tiene trabajos en cola
Sin embargo, si nada puede evitar que realice una prueba de integración completa. Se supone que ActiveJob test_helper.rb se usa con minitest no con rspec. Entonces debes reconstruir su funcionalidad. Puedes simplemente llamar
expect(ActiveJob::Base.queue_adapter.enqueued_jobs).to eq 1
sin requerir nada
Actualización 1: Como se notó dentro de un comentario. ActiveJob::Base.queue_adapter.enqueued_jobs
solo funciona configurándolo como queue_adapter en el modo de prueba.
# either within config/environment/test.rb
config.active_job.queue_adapter = :test
# or within a test setup
ActiveJob::Base.queue_adapter = :test
Tuve algunos problemas, tal vez porque no incluí ActiveJob :: TestHelper, pero esto funcionó para mí ...
En primer lugar, asegúrese de que tiene el adaptador de cola configurado para :test
como se muestran en las respuestas anteriores.
Por alguna razón, los trabajos de clear_enqueued_jobs
en el bloque after
no me funcionaron, pero la fuente muestra que podemos hacer lo siguiente: 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
Rspec 3.4 ahora tiene have_enqueued_job cocinado, lo que hace que sea mucho más fácil de probar:
it "enqueues a YourJob" do
expect {
get :your_action, {}
}.to have_enqueued_job(YourJob)
end
tiene otras sutilezas para have_enqueued_job
para permitirle verificar el (los) argumento (s) y el número de veces que debe ponerse en cola.
Prueba de carriles ActiveJob con 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