[英]Rails - How do you test ActionMailer sent a specific email in tests
目前在我的測試中,我做這樣的事情來測試電子郵件是否排隊等待發送
assert_difference('ActionMailer::Base.deliveries.size', 1) do
get :create_from_spreedly, {:user_id => @logged_in_user.id}
end
但是,如果 ia 控制器操作可以發送兩封不同的電子郵件,即如果注冊正常則向用戶發送一封電子郵件,或者如果出現問題則向管理員發送通知 - 我如何測試實際發送的是哪一封。 無論如何,上面的代碼都會通過。
從 Rails 3 開始,ActionMailer::Base.deliveries 是 Mail::Message 的數組。 從郵件文檔:
# mail['from'] = 'mikel@test.lindsaar.net'
# mail[:to] = 'you@test.lindsaar.net'
# mail.subject 'This is a test email'
# mail.body = 'This is a body'
#
# mail.to_s #=> "From: mikel@test.lindsaar.net\r\nTo: you@...
因此,在集成中測試您的郵件應該很容易
mail = ActionMailer::Base.deliveries.last
assert_equal 'mikel@test.lindsaar.net', mail['from'].to_s
assert_equal 'you@test.lindsaar.net', mail['to'].to_s
在測試期間使用 ActionMailer 時,所有郵件都放在一個名為deliveries
的大數組中。 您基本上正在做的(並且主要是足夠的)是檢查數組中是否存在電子郵件。 但是如果要專門檢查某封電子郵件,則必須知道數組中實際存儲的是什么。 幸運的是,電子郵件本身已被存儲,因此您可以遍歷數組並檢查每封電子郵件。
請參閱ActionMailer::Base以查看可用的配置方法,您可以使用這些方法來確定數組中存在哪些電子郵件。 一些最適合您的情況的方法可能是
recipients
: recipients
一個或多個電子郵件地址。 這些地址是您的電子郵件將被發送到的地方。 設置 To: 標題。subject
:您的電子郵件的主題。 設置主題:標題。使用當前的 Rspec 語法,我最終使用了以下內容:
last_email = ActionMailer::Base.deliveries.last
expect(last_email.to).to eq ['test@example.com']
expect(last_email.subject).to have_content 'Welcome'
我的測試上下文是一個功能規范,我想確保在注冊后向用戶發送歡迎電子郵件。
測試框架應該有一個出色的助手,它可以讓您斷言有關已發送電子郵件的某些條件。 是的,你可以用 ActionMailer.deliveries 自己做,但應該把這一切變成一個整潔的小塊
有點晚了,但它可能會幫助其他人:
您可以使用Email-spec ,一組 Rspec/Minitest 匹配器和 Cucumber 步驟。
截至2020(軌道6時代,大概前面介紹),你可以做到以下幾點:(使用SystemTest例子)TL; DR:使用assert_emails
從ActionMailer::TestHelper
和ActionMailer::Base.deliveries.last
訪問郵件本身。
require "application_system_test_case"
require 'test_helper'
require 'action_mailer/test_helper'
class ContactTest < ApplicationSystemTestCase
include ActionMailer::TestHelper
test "Send mail via contact form on landing page" do
visit root_url
fill_in "Message", with: 'message text'
# Asserting a mail is sent
assert_emails 1 do
click_on "Send"
end
# Asserting stuff within that mail
last_email = ActionMailer::Base.deliveries.last
assert_equal ['whatever'], last_email.reply_to
assert_equal "contact", last_email.subject
assert_match /Mail from someone/, last_email.body.to_s
end
end
官方文檔:
注意與上面系統測試中手動檢查郵件內容不同,您還可以測試是否使用了特定的郵件程序操作,如下所示:
assert_enqueued_email_with ContactMailer, :welcome, args: ["Hello", "Goodbye"]
還有一些其他方便的斷言,請參閱https://api.rubyonrails.org/v6.0.3.2/classes/ActionMailer/TestHelper.html#method-i-assert_emails 。
這是我找到的最好的方法。
1)包括這樣的動作郵件回調插件:
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)
等使用的那些。就是這樣!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.