How to test with RSpec if an email is delivered

喜欢而已 提交于 2019-11-30 12:03:06

问题


I'd like to test if an email is delivered if I call a controller method with :post. I'll use email_spec so I tried this snipped here: http://rubydoc.info/gems/email_spec/1.2.1/file/README.rdoc#Testing_In_Isolation

But it doesn't work, because I pass an instance of the model-object to the delivery-method and the instance is saved before the delivery.

I tried to create an other instance of the model-object, but then the id isn't the same.

My controller-method looks like this:

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

Do you have any idea to solve this?


回答1:


Assuming your test environment is set up in the usual fashion (that is, you have config.action_mailer.delivery_method = :test), then delivered emails are inserted into the global array ActionMailer::Base.deliveries as Mail::Message instances. You can read that from your test case and ensure the email is as expected. See here.




回答2:


Configure your test environment to accumulate sent mails in ActionMailer::Base.deliveries.

# config/environments/test.rb
config.action_mailer.delivery_method = :test

Then something like this should allow you to test that the mail was sent.

# 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

Note that my example uses RSpec 3 syntax.




回答3:


I know I'm late to the party with this one, but for future Googlers...

I think a better solution to this problem is answered here

The previously accepted answer is testing the Mailer itself (inside the controller spec). All you should be testing for here is that the Mailer gets told to deliver something with the right parameters.

You can then test the Mailer elsewhere to make sure it responds to those parameters correctly.

ReservationMailer.should_receive(:confirm_email).with(an_instance_of(Reservation))




回答4:


For the record, to anyone using rspec 3.4 and ActiveJob to send async emails, you could check this with:

expect {
  post :create, params
}.to have_enqueued_job.on_queue('mailers')



回答5:


This is way how to test that Mailer is called with right arguments. You can use this code in feature, controller or mailer spec:

delivery = double
expect(delivery).to receive(:deliver_now).with(no_args)

expect(ReservationMailer).to receive(:confirm_email)
  .with('reservation')
  .and_return(delivery)



回答6:


To add a little more, make sure if you're going to stub out a call using should_receive that you have an integration test elsewhere testing that you're actually calling the method correctly.

I've been bit a few times by changing a method that was tested elsewhere with should_receive and having tests still pass when the method call was broken.

If you prefer to test the outcome rather than using should_receive, shoulda has a nice matcher that works like the following:

it { should have_sent_email.with_subject(/is spam$/) }

Shoulda documentation

More information on using Shoulda Matchers with rSpec




回答7:


If you're using Capybara with Capybara Email and you sent an email to test@example.com, you can also use this method:

email = open_email('test@example.com')

And then you can test it like this:

expect(email.subject).to eq('SUBJECT')
expect(email.to).to eq(['test@example.com'])



回答8:


Try 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

more examples here: https://github.com/email-spec/email-spec#testing-in-isolation



来源:https://stackoverflow.com/questions/7284413/how-to-test-with-rspec-if-an-email-is-delivered

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!