如何使用Sidekiq测试Devise Async?

时间:2014-11-21 18:35:32

标签: ruby-on-rails-4 devise rspec-rails sidekiq devise-async

提前致谢! Sidekiq工作正常,但我无法用Devise Async测试它,或者我应该说我不能测试后者?

根据Sidekiq的文档,当测试模式设置为fake!时,任何给予worker的作业都会被推送到同一个worker的名为jobs的数组中。所以测试这个数组的增加是微不足道的。

但是,对于Devise Async,虽然它的后端包括Sidekiq::Worker,但它并不是那么简单。以下是我尝试测试的一小部分内容:

  • Devise::Async::Backend::Sidekiq.jobs
  • Devise::Mailer.deliveries
  • ActionMailer::Base.deliveries
  • Devise::Async::Backend::Worker.jobs

这些测试对象都没有指出尺寸的增加。由于Devise将其电子邮件作为模型回调发送,我尝试在模型和控制器规范中进行测试。使用Factory Girl和Database Cleaner,我也尝试了两种模式:事务和截断。毋庸置疑,我也尝试过两种Sidekiq模式:假的!和内联!。

我错过了什么?

2 个答案:

答案 0 :(得分:1)

documentation中所述,您可以将队列大小检查为

Sidekiq::Extensions::DelayedMailer.jobs.size

答案 1 :(得分:0)

正在研究这个问题,偶然发现gitlab做了一个漂亮的实现,我认为这可能有助于测试通过sidekiq队列推送的设计异步或电子邮件。 spec_helper.rb email_helpers.rb

spec_helper.rb

中添加这些行
# An inline mode that runs the job immediately instead of enqueuing it
require 'sidekiq/testing/inline'

# Requires supporting ruby files with custom matchers and macros, etc,
# in spec/support/ and its subdirectories.
Dir[Rails.root.join("spec/support/**/*.rb")].each { |f| require f }

RSpec.configure do |config|
  config.include EmailHelpers
  # other configurations line
end

并添加/spec/support/email_helpers.rb

module EmailHelpers
  def sent_to_user?(user)
    ActionMailer::Base.deliveries.map(&:to).flatten.count(user.email) == 1
  end

  def should_email(user)
    expect(sent_to_user?(user)).to be_truthy
  end

  def should_not_email(user)
    expect(sent_to_user?(user)).to be_falsey
  end
end

要运行测试,例如测试您的忘记密码,我假设您知道rspec,factorygirl,capybara  /spec/features/password_reset_spec.rb

require 'rails_helper'

feature 'Password reset', js: true do
  describe 'sending' do
    it 'reset instructions' do
      #FactoryGirl create
      user = create(:user)
      forgot_password(user)

      expect(current_path).to eq(root_path)
      expect(page).to have_content('You will receive an email in a few minutes')
      should_email(user)
    end
  end

  def forgot_password(user)
    visit '/user/login'
    click_on 'Forgot password?'
    fill_in 'user[email]', with: user.email
    click_on 'Reset my password'
    user.reload
  end
end

你会注意到在这个测试实现中

  1. 将导致sidekiq运行作业而不是将其排队,
  2. 必须调用用户模型电子邮件属性email,否则您只需替换上面的代码。
  3. ActionMailer::Base.deliveries.map(&:to).flatten.count(user.email) == 1查看ActionMailer :: Base.deliveries正在向user.email发送