Rails-Jak testować ActionMailer wysłany konkretny e-mail w testach

Obecnie w moich testach robię coś takiego, aby sprawdzić, czy e-mail jest w kolejce do wysłania

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

Ale jeśli ja akcja kontrolera może wysłać dwa różne e-maile, tj. jeden do użytkownika, jeśli rejestracja pójdzie dobrze lub powiadomienie do admina, jeśli coś poszło nie tak - jak mogę sprawdzić, który z nich rzeczywiście został wysłany. Powyższy kod przejdzie niezależnie.

Author: John Bachir, 2010-01-14

6 answers

Podczas korzystania z ActionMailer podczas testów, wszystkie wiadomości są umieszczane w dużej tablicy o nazwie deliveries. To, co w zasadzie robisz (i jest wystarczające głównie), to sprawdzanie, czy e-maile są obecne w tablicy. Ale jeśli chcesz dokładnie sprawdzić, czy nie ma określonej wiadomości e-mail, musisz wiedzieć, co jest faktycznie przechowywane w tablicy. Na szczęście same e-maile są przechowywane, dzięki czemu można iterację za pośrednictwem tablicy i sprawdzić każdy e-mail.

Zobacz ActionMailer::Base aby zobaczyć jaką konfigurację dostępne są metody, których można użyć do określenia, jakie wiadomości e-mail są obecne w tablicy. Niektóre z najbardziej odpowiednich metod dla Twojego przypadku to

  • recipients: pobiera jeden lub więcej adresów e-mail. Te adresy są adresami, na które zostanie dostarczony twój e-mail. Ustawia nagłówek na:.
  • subject: temat twojego maila. Ustawia temat: nagłówek.
 24
Author: Veger,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-14 16:09:00

Od rails 3 ActionMailer:: Base.delivery to tablica Mail:: Message ' s. From the mail documentation:

#  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: you@...

Od tego powinno być łatwo przetestować pocztę w integracji

mail = ActionMailer::Base.deliveries.last

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

assert_equal '[email protected]', mail['to'].to_s
 66
Author: todd,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-05-18 19:11:13

Używając bieżącej składni Rspec, skończyłem używając następującej:

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

Kontekstem mojego testu była Specyfikacja funkcji, w której chciałem upewnić się, że wiadomość powitalna zostanie wysłana do użytkownika po zarejestrowaniu się.

 16
Author: Neal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-06-20 20:54:09

Framework testowy shoulda posiada doskonały helper, który pozwala na spełnienie pewnych warunków dotyczących wysłanej wiadomości e-mail. Tak, możesz to zrobić sam z ActionMailer.dostawy, ale powinno sprawić, że wszystko będzie jednym schludnym małym blokiem

 3
Author: RyanWilcox,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-14 16:30:40

Trochę za późno, ale może pomóc innym:

Możesz użyć Email-spec, kolekcji matcherów Rspec/Minitest i kroków ogórkowych.

 2
Author: guapolo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-16 06:41:24

Oto najlepszy sposób, jaki znalazłem.

1) Dołącz action mailer callbacks plugin taki jak ten:

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

Naprawdę nie używam głównych funkcji wtyczki, ale zapewnia miłą funkcjonalność bycia w stanie dowiedzieć się, Która metoda została użyta do wysłania wiadomości e-mail.

2) Teraz możesz umieścić kilka metod w swoim test_helper.RB jak to:

  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) Teraz możesz pisać takie słodkie testy:

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

Tutaj "broadcast" i " mailing_failed" są nazwami metod w mojej klasie Base ActionMailer::. Są to te, których zwykle używasz, wywołując Mailer.deliver_broadcast(some_data) lub Mailer.deliver_failed_mailing(some_data) itp. To jest to!

 1
Author: Brian Armstrong,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-05-12 03:23:27