Comment vérifier ce qui est mis en file D'attente dans ActiveJob en utilisant Rspec
je travaille sur une méthode reset_password dans une application de L'API Rails. Lorsque ce point final est atteint, une tâche active est mise en file d'attente qui déclenche une requête à Mandrill (notre client de messagerie transactionnel). Je suis en train d'essayer d'écrire les tests pour m'assurer que L'ActiveJob est mise en file d'attente correctement lorsque le terminal du contrôleur est touché.
def reset_password
@user = User.find_by(email: params[:user][:email])
@user.send_reset_password_instructions
end
les instructions send_reset_password_instructions créent des URLs etc avant de créer L'ActiveJob dont le code est ci-dessous:
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
À le moment où nous n'utilisons pas d'adaptateur pour L'ActiveJob, donc je veux juste vérifier avec Rspec que L'ActiveJob est en file d'attente.
actuellement mon test ressemble à quelque chose comme ceci (j'utilise factory girl pour créer l'utilisateur):
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
Tout fonctionne en réalité, j'ai juste besoin de créer les tests!
j'utilise ruby 2.1.2 et rails 4.1.6.
Je ne vois aucune documentation ou aide nulle part sur le web sur la façon de tester sur ce si toute aide serait grandement apprécié!
6 réponses
la réponse acceptée ne fonctionne plus pour moi, donc j'ai essayé la suggestion de Michael H. dans les commentaires, qui fonctionne.
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
vous n'avez vraiment pas besoin de tester la fonctionnalité ActiveJob. Il suffit de tester que votre code l'appelle correctement en le frappant hors
expect(MyJob).to receive(:perform_later).once
post :reset_password, user: { email: user.email }
les créateurs de L'ActiveJob ont utilisé les mêmes techniques pour leurs tests unitaires. Voir GridJob Testobject
ils créent une GridJob testmock dans leurs tests et supplantent la méthode perform, de sorte qu'elle ajoute seulement des jobs à un tableau personnalisé, ils appellent JobBuffer. À la fin, ils vérifient si le tampon a travaux en file d'attente
cependant si rien ne peut vous empêcher de faire un test d'intégration complet. The ActiveJob test_helper.rb est censé être utilisé avec minitest pas avec rspec. Donc vous devez reconstruire sa fonctionnalité. Vous pouvez les appeler
expect(ActiveJob::Base.queue_adapter.enqueued_jobs).to eq 1
sans exiger rien
mise à Jour 1:
Comme noté dans un commentaire.
ActiveJob::Base.queue_adapter.enqueued_jobs
ne fonctionne qu'en paramétrant le jeu_adapter en mode test.
# either within config/environment/test.rb
config.active_job.queue_adapter = :test
# or within a test setup
ActiveJob::Base.queue_adapter = :test
Rspec 3.4 a have_enqueued_job cuits, ce qui rend le test beaucoup plus facile:
it "enqueues a YourJob" do
expect {
get :your_action, {}
}.to have_enqueued_job(YourJob)
end
il a d'autres subtilités pour have_enqueued_job
pour vous permettre de vérifier l'argument(s) et le nombre de fois où il doit être mis en file d'attente.
Il y a un nouveau RSpec extension ce qui rend votre vie plus facile.
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
les Rails ActiveJob avec 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
j'ai eu quelques problèmes, peut-être parce que je n'ai pas inclus ActiveJob::TestHelper, mais cela a fonctionné pour moi...
tout d'abord, assurez-vous que l'adaptateur de file d'attente est réglé sur :test
comme le montrent les réponses ci-dessus.
Pour une raison quelconque clear_enqueued_jobs
emplois after
bloc ne fonctionne pas pour moi, mais source montre nous pouvons faire ce qui suit: 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