如果我使用:post调用控制器方法,我想测试是否发送了电子邮件。我将使用email_spec,所以我在这里尝试了这个:http://rubydoc.info/gems/email_spec/1.2.1/file/README.rdoc#Testing_In_Isolation
但它不起作用,因为我将model-object的一个实例传递给delivery-method,并且在传递之前保存了实例。
我试图创建一个model-object的另一个实例,但后面的id不一样。
我的控制器方法如下所示:
def create
@params = params[:reservation]
@reservation = Reservation.new(@params)
if @reservation.save
ReservationMailer.confirm_email(@reservation).deliver
redirect_to success_path
else
@title = "Reservation"
render 'new'
end
end
你有什么想法解决这个问题吗?
答案 0 :(得分:51)
假设您的测试环境是以通常的方式设置的(即,您有config.action_mailer.delivery_method = :test
),那么已发送的电子邮件将作为ActionMailer::Base.deliveries
实例插入到全局数组Mail::Message
中。您可以从测试用例中读取该内容,并确保电子邮件符合预期。请参阅here。
答案 1 :(得分:20)
配置您的测试环境,以便在ActionMailer::Base.deliveries
累积发送的邮件。
# config/environments/test.rb
config.action_mailer.delivery_method = :test
然后这样的事情应该允许你测试邮件的发送。
# Sample parameters you would expect for POST #create.
def reservation_params
{ "reservation" => "Drinks for two at 8pm" }
end
describe MyController do
describe "#create" do
context "when a reservation is saved" do
it "sends a confirmation email" do
expect { post :create, reservation_params }.to change { ActionMailer::Base.deliveries.count }.by(1)
end
end
end
end
请注意,我的示例使用RSpec 3语法。
答案 2 :(得分:18)
我知道我已经迟到了这个,但是对于未来的Google员工......
我认为这个问题的更好解决方案已经回答here
之前接受的答案是测试Mailer本身(在控制器规范内)。你应该在这里测试的是,梅勒被告知要提供具有正确参数的东西。
然后,您可以在其他地方测试Mailer,以确保它正确响应这些参数。
ReservationMailer.should_receive(:confirm_email)。随着(an_instance_of(预约))
答案 3 :(得分:4)
为了记录,对于使用rspec 3.4和ActiveJob发送异步电子邮件的任何人,您可以通过以下方式检查:
expect {
post :create, params
}.to have_enqueued_job.on_queue('mailers')
答案 4 :(得分:2)
这是如何测试使用正确参数调用Mailer的方法。您可以在功能,控制器或邮件程序规范中使用此代码:
delivery = double
expect(delivery).to receive(:deliver_now).with(no_args)
expect(ReservationMailer).to receive(:confirm_email)
.with('reservation')
.and_return(delivery)
答案 5 :(得分:1)
要添加更多内容,请确保您是否要使用should_receive存根调用,您在其他地方进行了集成测试,测试您实际上正在正确调用该方法。
通过更改使用should_receive在别处测试的方法并且在方法调用被破坏时测试仍然通过,我已经有几次了。
如果您更喜欢测试结果而不是使用should_receive,那么shoulda有一个很好的匹配器,其工作方式如下:
it { should have_sent_email.with_subject(/is spam$/) }
答案 6 :(得分:1)
如果您使用Capybara Email Capybara 并且您向test@example.com
发送了电子邮件,则还可以使用此方法:
email = open_email('test@example.com')
然后你可以像这样测试它:
expect(email.subject).to eq('SUBJECT')
expect(email.to).to eq(['test@example.com'])
答案 7 :(得分:-1)
describe "POST /signup (#signup)" do
it "should deliver the signup email" do
# expect
expect(UserMailer).to(receive(:deliver_signup).with("email@example.com", "Jimmy Bean"))
# when
post :signup, "Email" => "email@example.com", "Name" => "Jimmy Bean"
end
end
此处有更多示例:https://github.com/email-spec/email-spec#testing-in-isolation