我正在尝试使用this railscast为电子邮件添加一些测试,但我得到undefined method 'to' for nil:NilClass
。
电子邮件实际上是通过后台工作人员使用Sidekiq处理的,我知道他们在生产中正常发送,并且在我将require 'sidekiq/testing'
添加到spec_helper.rb
<之前他们会发送/ p>
所以基本上我的问题是如何在Sidekiq中访问电子邮件?我试图让工作人员处理电子邮件但仍然遇到同样的错误。
规格/支持/ mailer_macros.rb
module MailerMacros
def last_email
ActionMailer::Base.deliveries.last
end
def reset_email
ActionMailer::Base.deliveries = []
end
end
规格/ spec_helper.rb
require 'sidekiq/testing'
...
config.include MailerMacros
config.before(:each) { reset_email }
配置/环境/ 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") }
时,我得到同样的错误。
答案 0 :(得分:5)
当需要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
答案 1 :(得分:1)
除了cmaitchison的回答,我还是这样修好了(在他们的维基上: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