Ruby-on-rails 如何使用 Rspec 检查 ActiveJob 中排队的内容
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/26274954/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to check what is queued in ActiveJob using Rspec
提问by mylescc
I'm working on a reset_password method in a Rails API app. When this endpoint is hit, an ActiveJob is queued that will fire off a request to Mandrill (our transactional email client). I'm currently trying to write the tests to ensure that that the ActiveJob is queued correctly when the controller endpoint is hit.
我正在 Rails API 应用程序中使用 reset_password 方法。当这个端点被击中时,一个 ActiveJob 排队,它将向 Mandrill(我们的交易电子邮件客户端)发出请求。我目前正在尝试编写测试以确保在命中控制器端点时 ActiveJob 正确排队。
def reset_password
@user = User.find_by(email: params[:user][:email])
@user.send_reset_password_instructions
end
The send_reset_password_instructions creates some url's etc before creating the ActiveJob which's code is below:
send_reset_password_instructions 在创建 ActiveJob 之前创建了一些 url 等,其代码如下:
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
At the moment we are not using any adapters for the ActiveJob, so I just want to check with Rspec that the ActiveJob is queued.
目前我们没有为 ActiveJob 使用任何适配器,所以我只想使用 Rspec 检查 ActiveJob 是否已排队。
Currently my test looks something like this (I'm using factory girl to create the user):
目前我的测试看起来像这样(我使用 factory girl 创建用户):
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
Everything works in reality, I just need to create the tests!
一切都在现实中工作,我只需要创建测试!
I'm using ruby 2.1.2 and rails 4.1.6.
我正在使用 ruby 2.1.2 和 rails 4.1.6。
I can't see any documentation or help anywhere on the web on how to test on this so any help would be greatly appreciated!
我在网络上的任何地方都看不到有关如何对此进行测试的任何文档或帮助,因此将不胜感激!
回答by Josh Smith
The accepted answer no longer works for me, so I tried Michael H.'s suggestion in the comments, which works.
接受的答案不再适合我,所以我在评论中尝试了 Michael H. 的建议,这很有效。
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
回答by dre-hh
You really don't need to test ActiveJob functionality. Just test that your code calls it properly by stubbing it out
您真的不需要测试 ActiveJob 功能。只需通过存根测试您的代码是否正确调用它
expect(MyJob).to receive(:perform_later).once
post :reset_password, user: { email: user.email }
The creators of the ActiveJob have used the same techniques for their unit tests. See GridJob Testobject
ActiveJob 的创建者在他们的单元测试中使用了相同的技术。参见GridJob 测试对象
They create a testmock GridJob in their tests and override the perform method, so that it only adds jobs to a custom Array, they call JobBuffer. At the end they test, whether the buffer has jobs enqueued
他们在他们的测试中创建了一个 testmock GridJob 并覆盖了 perform 方法,这样它只会将作业添加到自定义数组中,他们调用JobBuffer。最后他们测试缓冲区是否有作业入队
However if nothing can't stop you of doing a full integration test. The ActiveJob test_helper.rbis supposed to be used with minitest not with rspec. So you have to rebuild it's functionalitity. You can just call
但是,如果没有什么不能阻止您进行完整的集成测试。ActiveJob test_helper.rb应该与 minitest 一起使用,而不是与 rspec 一起使用。所以你必须重建它的功能。你可以打电话
expect(ActiveJob::Base.queue_adapter.enqueued_jobs).to eq 1
without requiring anything
不需要任何东西
Update 1:As noticed within a comment.
ActiveJob::Base.queue_adapter.enqueued_jobsworks only by setting it the queue_adapter into test mode.
更新 1:正如评论中所注意到的。
ActiveJob::Base.queue_adapter.enqueued_jobs只能通过将 queue_adapter 设置为测试模式来工作。
# either within config/environment/test.rb
config.active_job.queue_adapter = :test
# or within a test setup
ActiveJob::Base.queue_adapter = :test
回答by tirdadc
Rspec 3.4now has have_enqueued_jobcooked in, which makes this a lot easier to test:
Rspec 3.4现在已经加入了have_enqueued_job,这使得它更容易测试:
it "enqueues a YourJob" do
expect {
get :your_action, {}
}.to have_enqueued_job(YourJob)
end
it has other niceties for have_enqueued_jobto allow you to check the argument(s) and the number of times it should be queued up.
它还有其他优点,have_enqueued_job可以让您检查参数和它应该排队的次数。
回答by ChuckJHardy
Testing Rails ActiveJob with 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
回答by KARASZI István
There is a new rspec extensionwhich makes your life easier.
有一个新的rspec 扩展,让你的生活更轻松。
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
回答by Archernar
I had some problems, maybe because I didn't include ActiveJob::TestHelper, but this worked for me...
我遇到了一些问题,也许是因为我没有包含 ActiveJob::TestHelper,但这对我有用...
Firstly ensure, that you have the queue adapter set to :testas above answers show.
首先确保您将队列适配器设置:test为如上答案所示。
For some reason clear_enqueued_jobsjobs in the afterblock didn't work for me, but the sourceshows we can do the following: enqueued_jobs.clear
出于某种原因clear_enqueued_jobs,after块中的工作对我不起作用,但来源显示我们可以执行以下操作: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

