Как протестировать Rspec, если отправлено электронное письмо
Я бы хотел проверить, отправлено ли электронное письмо, если я вызову метод контроллера с помощью: post. Я буду использовать email_spec, поэтому я попробовал это здесь: http://rubydoc.info/gems/email_spec/1.2.1/file/README.rdoc#Testing_In_Isolation
Но это не сработает, потому что я передаю экземпляр объекта модели методу доставки, и экземпляр сохраняется до доставки.
Я попытался создать другой экземпляр объекта 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
Есть ли у вас идея решить эту проблему?
Ответы
Ответ 1
Предполагая, что ваша тестовая среда настроена обычным способом (т.е. у вас есть config.action_mailer.delivery_method = :test
), тогда отправленные электронные письма вставляются в глобальный массив ActionMailer::Base.deliveries
как Mail::Message
экземпляры. Вы можете прочитать это из своего тестового примера и убедиться, что сообщение электронной почты как ожидается. См. здесь.
Ответ 2
Настройте тестовую среду для накопления отправленных сообщений в 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.
Ответ 3
Я знаю, что опаздываю на вечеринку с этим, но для будущих гуглеров...
Я думаю, что лучшее решение этой проблемы будет отвечать здесь
Ранее принятый ответ проверяет сам Mailer (внутри спецификации контроллера). Все, что вы должны тестировать здесь, это то, что Mailer получает сообщение о том, чтобы доставить что-то с правильными параметрами.
Затем вы можете проверить Mailer в другом месте, чтобы убедиться, что он правильно отвечает на эти параметры.
ReservationMailer.should_receive (: confirm_email).с (an_instance_of (резервирование))
Ответ 4
Для записи любому, кто использует rspec 3.4 и ActiveJob для отправки асинхронных сообщений электронной почты, вы можете проверить это с помощью
expect {
post :create, params
}.to have_enqueued_job.on_queue('mailers')
Ответ 5
Это способ проверки того, что Mailer вызывается с правильными аргументами. Вы можете использовать этот код в спецификации функции, контроллера или почтовой программы:
delivery = double
expect(delivery).to receive(:deliver_now).with(no_args)
expect(ReservationMailer).to receive(:confirm_email)
.with('reservation')
.and_return(delivery)
Ответ 6
Чтобы добавить немного больше, убедитесь, что вы собираетесь отключить вызов, используя метод was_receive, который у вас есть тест интеграции в другом месте, проверяющий, что вы действительно вызываете метод правильно.
Я несколько раз бил, меняя метод, который был протестирован в другом месте с помощью функции should_receive, и тесты по-прежнему проходят, когда вызов метода был нарушен.
Если вы предпочитаете проверять результат, а не использовать should_receive, у shoulda есть хороший помощник, который работает следующим образом:
it { should have_sent_email.with_subject(/is spam$/) }
Документация по документации
Дополнительная информация об использовании совпадений с запятой с rSpec
Ответ 7
Если вы используете Capybara с электронной почтой [email protected]
и отправили электронное письмо на [email protected]
, вы также можете использовать этот метод:
email = open_email('[email protected]')
И тогда вы можете проверить это следующим образом:
expect(email.subject).to eq('SUBJECT')
expect(email.to).to eq(['[email protected]'])
Ответ 8
Попробуйте email-spec
describe "POST /signup (#signup)" do
it "should deliver the signup email" do
# expect
expect(UserMailer).to(receive(:deliver_signup).with("[email protected]", "Jimmy Bean"))
# when
post :signup, "Email" => "[email protected]", "Name" => "Jimmy Bean"
end
end
больше примеров здесь: https://github.com/email-spec/email-spec#testing-in-isolation