簡體   English   中英

Rails - 你如何測試 ActionMailer 在測試中發送了特定的電子郵件

[英]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以查看可用的配置方法,您可以使用這些方法來確定數組中存在哪些電子郵件。 一些最適合您的情況的方法可能是

  • recipientsrecipients一個或多個電子郵件地址。 這些地址是您的電子郵件將被發送到的地方。 設置 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_emailsActionMailer::TestHelperActionMailer::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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM