如果发送电子邮件,如何使用Rspec进行测试

时间:2011-09-02 13:50:56

标签: ruby-on-rails-3 rspec2

如果我使用: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

你有什么想法解决这个问题吗?

8 个答案:

答案 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$/) }

Shoulda documentation

More information on using Shoulda Matchers with rSpec

答案 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)

尝试email-spec

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