Подтвердить что ты не робот

Rails - как вы протестируете ActionMailer, отправили конкретное письмо в тестах

В настоящее время в моих тестах я делаю что-то вроде этого, чтобы проверить, отправлено ли электронное письмо в очередь

assert_difference('ActionMailer::Base.deliveries.size', 1) do       
  get :create_from_spreedly, {:user_id => @logged_in_user.id}
end

но если я действие контроллера может отправлять два разных письма, то есть один для пользователя, если регистрация прекрасна или уведомление администратора, если что-то пошло не так - как я могу проверить, какой из них действительно отправлен. Приведенный выше код будет проходить независимо.

4b9b3361

Ответ 1

При использовании ActionMailer во время тестов все письма помещаются в большой массив с именем deliveries. То, что вы в основном делаете (и в основном достаточное), проверяет наличие электронных писем в массиве. Но если вы хотите специально проверить наличие определенного электронного письма, вы должны знать, что на самом деле хранится в массиве. К счастью, сами электронные письма хранятся, поэтому вы можете проходить через массив и проверять каждое электронное письмо.

См. ActionMailer:: Base, чтобы узнать, какие методы настройки доступны, которые вы можете использовать для определения того, какие электронные письма присутствуют в массиве. Некоторые из наиболее подходящих методов для вашего случая, вероятно, являются

  • recipients: принимает один или несколько адресов электронной почты. Эти адреса будут отправлены по электронной почте. Устанавливает заголовок To:.
  • subject: тема вашего письма. Устанавливает заголовок Subject:.

Ответ 2

Начиная с рельсов 3 ActionMailer :: Base.deliveries является массивом Mail :: Message. Из почтовой документации:

#  mail['from'] = '[email protected]'
#  mail[:to]    = '[email protected]'
#  mail.subject 'This is a test email'
#  mail.body    = 'This is a body'
# 
#  mail.to_s #=> "From: [email protected]\r\nTo: [email protected]

От этого должно быть легко проверить свою почту в интеграции

mail = ActionMailer::Base.deliveries.last

assert_equal '[email protected]', mail['from'].to_s

assert_equal '[email protected]', mail['to'].to_s

Ответ 3

Используя текущий синтаксис Rspec, я закончил использовать следующее:

last_email = ActionMailer::Base.deliveries.last
expect(last_email.to).to eq ['[email protected]']
expect(last_email.subject).to have_content 'Welcome'

Контекст моего теста был спецификацией функции, где я хотел убедиться, что после регистрации было отправлено приветственное письмо пользователю.

Ответ 4

База тестов shoulda имеет отличный помощник, который позволяет вам утверждать определенные условия для отправленного сообщения электронной почты. Да, вы можете сделать это самостоятельно с помощью ActionMailer.deliveries, но shoulda делает все это одним аккуратным небольшим блоком.

Ответ 5

Немного поздно, но это может помочь другим:

Вы можете использовать Email-spec, набор совпадений Rspec/Minitest и шаги Cucumber.

Ответ 6

Вот лучший способ, который я нашел для этого.

1) Включите плагин action mailer обратные вызовы:

script/plugin install git://github.com/AnthonyCaliendo/action_mailer_callbacks.git

Я не использую основные функции плагина, но он обеспечивает отличную функциональность, позволяющую выяснить, какой метод был использован для отправки электронной почты.

2) Теперь вы можете поместить некоторые методы в свой test_helper.rb следующим образом:

  def assert_sent(method_name)
    assert sent_num_times(method_name) > 0
  end

  def assert_not_sent(method_name)
    assert sent_num_times(method_name) == 0
  end

  def assert_sent_once(method_name)
    assert sent_num_times(method_name) == 1
  end

  def sent_num_times(method_name)
    count = 0
    @emails.each do |email|
      count += 1 if method_name == email.instance_variable_get("@method_name")
    end
    count
  end

3) Теперь вы можете написать сладкие тесты следующим образом:

require 'test_helper'
class MailingTest < ActionController::IntegrationTest

  def setup
    @emails = ActionMailer::Base.deliveries
    @emails.clear
  end

  test "should send a mailing" do
    assert_difference "Mailing.count", 1 do
      feeds(:feed1).generate_mailing
    end

    assert_sent_once "broadcast"
    assert_not_sent "failed_mailing"
  end
end

Здесь "broadcast" и "mailing_failed" - это имена методов в моем классе ActionMailer:: Base. Это те, которые вы обычно используете, вызывая Mailer.deliver_broadcast(some_data) или Mailer.deliver_failed_mailing(some_data) и т.д. Что это!