2010-01-14 2 views
37

Zeit in meinen Tests, die ich so etwas tun zu testen, ob eine E-Mail-Warteschlange gestellt wirdRails - Wie gesendet Sie testen Action eine bestimmte E-Mail in Tests

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

aber wenn ia Controller-Aktion können zwei schicken verschiedene E-Mails, dh eine an den Benutzer, wenn sich die Anmeldung in Ordnung befindet oder eine Benachrichtigung an den Administrator, wenn etwas schief gelaufen ist - wie kann ich testen, welche tatsächlich gesendet wurde? Der obige Code würde unabhängig davon bestehen.

Antwort

22

Wenn Sie den ActionMailer während der Tests verwenden, werden alle Mails in einem großen Array namens deliveries abgelegt. Was Sie im Grunde tun (und meistens ausreichend ist), ist zu prüfen, ob E-Mails im Array vorhanden sind. Wenn Sie jedoch gezielt nach einer bestimmten E-Mail suchen möchten, müssen Sie wissen, was tatsächlich im Array gespeichert ist. Zum Glück sind die E-Mails selbst gespeichert, so dass Sie in der Lage sind, das Array zu durchlaufen und jede E-Mail zu überprüfen.

Siehe ActionMailer::Base, um zu sehen, welche Konfigurationsmethoden zur Verfügung stehen, mit denen Sie feststellen können, welche E-Mails im Array vorhanden sind. Einige der am besten geeigneten Methoden für Ihren Fall sind wahrscheinlich

  • recipients: Nimmt eine oder mehrere E-Mail-Adressen. An diese Adressen wird Ihre E-Mail gesendet. Setzt den An: Header.
  • subject: Der Betreff Ihrer E-Mail. Setzt den Betreff: Überschrift.
  • 3

    Das Testframework shoulda hat einen ausgezeichneten Helfer, mit dem Sie bestimmte Bedingungen über eine E-Mail bestätigen können, die gesendet wurde. Ja, du könntest es selbst mit ActionMailer.deliveries machen, aber shoja macht alles einen netten kleinen Block

    +1

    das ist der 'have_sent_email' Matcher http://www.rubydoc.info/gems/shoulda/2.11.3/Shoulda/ActionMailer/Machers (zB' it {sollte_mit_email.with_subject (/ spam /). From (' [email protected] '). mit_body (/ spam /). to ([email protected]')} –

    1

    Hier ist der beste Weg, den ich gefunden habe, es zu tun.

    1) Fügen Sie die action mailer callbacks Plugin wie folgt aus:

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

    ich wirklich nicht die Hauptfunktionen des Plugins verwenden, aber es bietet die schöne Funktionalität in der Lage, um herauszufinden, welche Methode verwendet wurde, senden eine E-Mail.

    2) Jetzt können Sie einige Methoden in Ihrem test_helper.rb so:

    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) Jetzt können Sie süß Tests wie folgt schreiben:

    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 
    

    hier "Sendung" und "mailing_failed" sind die Namen der Methoden in meiner ActionMailer :: Base-Klasse. Dies sind diejenigen, die Sie normalerweise verwenden, indem Sie Mailer.deliver_broadcast(some_data) oder Mailer.deliver_failed_mailing(some_data) usw. anrufen. Das ist es!

    60

    Ab Rails 3 ActionMailer :: Base.deliveries ist ein Array von Mail :: Message's.Von der Mail-Dokumentation:

    # 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] 
    

    aus, dass es einfach sein sollte, Ihre E-Mail ist in einer Integrations

    mail = ActionMailer::Base.deliveries.last 
    
    assert_equal '[email protected]', mail['from'].to_s 
    
    assert_equal '[email protected]', mail['to'].to_s 
    
    +1

    Sie können auch verwenden: "assert ActionMailer :: Base.deliveries.size> = 1 (oder == 2) "um zu prüfen, ob mehrere E-Mails gesendet werden. und um mehrere Themen zu überprüfen, und E-Mails verwenden" ActionMailer :: Base.deliveries.last (2) " –

    15

    Mit aktueller Rspec Syntax zu testen, wurde ich folgende mit bis:

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

    Der Kontext meines Tests war eine Feature-Spezifikation, bei der ich sicherstellen wollte, dass nach der Anmeldung eine Willkommens-E-Mail an einen Benutzer gesendet wurde.

    1

    ein wenig spät, aber es kann anderen helfen:

    Sie Email-spec, eine Sammlung von Rspec/Minitest Matcher und Gurke Schritte verwenden könnte.

    Verwandte Themen