2010-01-14 1 views
37

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

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

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

ответ

22

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

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

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

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

+1

это совпадение 'has_sent_email' http://www.rubydoc.info/gems/shoulda/2.11.3/Shoulda/ActionMailer/Matchers (например,' it {should have_sent_email.with_subject (/ spam /). From (' [email protected] '). with_body (/ spam /). to ([email protected]')} ' –

1

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

1) Включите action mailer callbacks плагин так:

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 

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

60

As of rails 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 
+1

Вы также можете использовать:" assert ActionMailer :: Base.deliveries.size> = 1 (или == 2) », чтобы отправить несколько писем. и для проверки нескольких объектов и писем используйте« ActionMailer :: Base.deliveries.last (2) » –

15

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

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

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

1

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

Вы можете использовать Email-spec, коллекция Rspec/MiniTest matchers и шаги огурца.