【问题标题】:Testing email: last email is nil when sent through a background worker测试电子邮件:通过后台工作人员发送时,最后一封电子邮件为零
【发布时间】:2013-03-23 15:54:10
【问题描述】:

我正在尝试使用 this railscast 为电子邮件添加一些测试,但我得到的是 undefined method 'to' for nil:NilClass。

这些电子邮件实际上是通过使用Sidekiq 的后台工作人员处理的,我知道它们可以正常发送,因为它们在生产中工作,而且它们会在我将require 'sidekiq/testing' 添加到spec_helper.rb 之前发送

所以基本上我的问题是如何在 Sidekiq 中访问电子邮件?我试图让工作人员处理电子邮件,但仍然遇到同样的错误。

spec/support/mailer_macros.rb

module MailerMacros
  def last_email
    ActionMailer::Base.deliveries.last
  end

  def reset_email
    ActionMailer::Base.deliveries = []
  end
end

spec/spec_helper.rb

require 'sidekiq/testing'
...
config.include MailerMacros
config.before(:each) { reset_email }

config/environments/test.rb

config.action_mailer.delivery_method = :test
config.action_mailer.default_url_options = { host: 'localhost:8080' }

控制器/tickets_controller.rb

def create
  @ticket = current_user.tickets.build(params[:ticket])   
  if @ticket.save
    Sidekiq::Client.enqueue(TicketNotifier, @ticket.id)
    flash[:success] = "Your ticket has been submitted successfully."
    redirect_to ticket_path(@ticket)
  else
    render 'new'
  end
end

部分规范:

require 'spec_helper'

describe "Tickets" do
  subject { page }

  describe "when creating a new ticket successfully" do
    before do
      login_as_user
      visit new_ticket_path
      fill_in "Subject", with: "Test ticket"
      fill_in "Description", with: "This is a test ticket"
      select 'Billing', from: "ticket[category]" 
      click_button "Submit Ticket"
    end

    specify { last_email.to.should include("admin@email.com") }
    # the rest tests the tickets#show view
    it { should have_selector('title', text: "Ticket #1") }
    it { should have_content("ticket has been submitted successfully") }
    ...
  end
end

当我改用specify { ActionMailer::Base.deliveries.last.to.should include("admin@email.com") } 时,我得到了同样的错误。

【问题讨论】:

  • 你可以试试这个吗? specify { MailerMacros.last_email.should include(@user.email) }
  • 然后我得到 undefined method 'last_email' for MailerMacros:Module,根据我之前运行的 railscast 和类似宏,last_email 应该可以工作。
  • 我的错,你是对的,我没有经过适当思考就猜到了。刚刚经历了那个 railscast,它即将到来 nil:NilClass 在你的情况下,所以我只能期待一个原因是 is the mail actually being sent?
  • 是的,如果我删除 require 'sidekiq/testing',Sidekiq 实际上会向我的收件箱发送一封电子邮件。

标签: ruby-on-rails email testing rspec sidekiq


【解决方案1】:

当需要sidekiq/testing 而不是sidekiq/testing/inline 时,作业会被放入队列中,但在给出这样的命令之前不会执行:

Sidekiq::Extensions::DelayedMailer.drain

我在我的规范中使用了这样的辅助方法:

def process_async
  EventWorker.drain
  Sidekiq::Extensions::DelayedMailer.drain
end

EventWorker 可能是我的应用程序中的自定义工作线程,Sidekiq::Extensions::DelayedMailer 是 Sidekiq 默认发送延迟邮件的位置。

然后我可以有这样的规范:

#do stuff that should send an email and trigger other sidekiq events
...
process_async
...
#assert the email was sent correctly

SideKiq wiki 上对这一切都有很好的解释:https://github.com/mperham/sidekiq/wiki/Testing

【讨论】:

  • 太棒了!感谢您解释它是如何工作的,我阅读了 wiki,但没有完全理解它。
【解决方案2】:

除了 cmaitchison 的回答之外,我还修复了它(在他们的 wiki 上:https://github.com/mperham/sidekiq/wiki/Testing#rspec)

require 'sidekiq/testing'

RSpec.configure do |config|
  config.before(:each) do
    # Clears out the jobs for tests using the fake testing
    Sidekiq::Worker.clear_all

    if example.metadata[:sidekiq] == :fake
      Sidekiq::Testing.fake!
    elsif example.metadata[:sidekiq] == :inline
      Sidekiq::Testing.inline!
    elsif example.metadata[:type] == :acceptance
      Sidekiq::Testing.inline!
    else
      Sidekiq::Testing.fake!
    end
  end
end

然后像这样进行测试:

describe "Tickets", :sidekiq => :inline do
  subject { page }

  describe "when creating a new ticket successfully" do
    before do
      login_as_user
      visit new_ticket_path
      fill_in "Subject", with: "Test ticket"
      fill_in "Description", with: "This is a test ticket"
      select 'Billing', from: "ticket[category]" 
      click_button "Submit Ticket"
    end

    specify { last_email.to.should include("admin@email.com") }
    # the rest tests the tickets#show view
    it { should have_selector('title', text: "Ticket #1") }
    it { should have_content("ticket has been submitted successfully") }
    ...
  end
end

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-10
    • 1970-01-01
    • 1970-01-01
    • 2015-10-13
    • 1970-01-01
    相关资源
    最近更新 更多