【Rails】ActionMailer のテストで Mail::Matchers を使う
はじめに
CBcloud Advent Calendar 2020 の2日目の記事です。
本記事では、メール送信の単体テストの際、ActionMailer が依存している Mail に含まれている Mail::Matchers
を RSpec のマッチャとして利用する方法を紹介します。
また、比較対象として、以下の2つも同時に記載します。
- Rails Guides に記載されているテスト方法
- RSpec のドキュメントに記載されているテスト方法
最後に、Mail::Matchers
を使った例の紹介と、実際に動くサンプルコードを添付します。
動作確認環境
- ruby 2.7.2p137 (2020-10-01 revision 5445e04352) [x86_64-darwin19]
- actionmailer (6.0.3.4)
- rspec (3.10.0)
テストコード
Rails Guides に記載されているテスト方法
require 'test_helper'
class UserMailerTest < ActionMailer::TestCase
test "invite" do
# Create the email and store it for further assertions
email = UserMailer.create_invite('[email protected]',
'[email protected]', Time.now)
# Send the email, then test that it got queued
assert_emails 1 do
email.deliver_now
end
# Test the body of the sent email contains what we expect it to
assert_equal ['[email protected]'], email.from
assert_equal ['[email protected]'], email.to
assert_equal 'You have been invited by [email protected]', email.subject
assert_equal read_fixture('invite').join, email.body.to_s
end
end
RSpec のドキュメントに記載されているテスト方法
require "rails_helper"
RSpec.describe NotificationsMailer, :type => :mailer do
describe "notify" do
let(:mail) { NotificationsMailer.signup }
it "renders the headers" do
expect(mail.subject).to eq("Signup")
expect(mail.to).to eq(["[email protected]"])
expect(mail.from).to eq(["[email protected]"])
end
it "renders the body" do
expect(mail.body.encoded).to match("Hi")
end
end
end
Mail::Matchers を使ったテスト方法
ActionMailer の依存で Mail gem は既にインストール済みなので、導入手順は簡単です。
- RSpec の設定で、
Mail::Matchers
を include する - ActionMailer のテストで
Mail::Matchers
が提供するマッチャを使う
以下が実際に Mail::Matchers
を使って書いたコードです。
比較のため、最初のコンテキストでは先述した RSpec のドキュメントに記載されたサンプルを踏襲したコードを実装しています。
RSpec.configure do |config|
config.include Mail::Matchers, type: :mailer
end
RSpec.describe NotificationsMailer, type: :mailer do
before do
ActionMailer::Base.deliveries.clear
end
describe '#signup' do
# @see: https://relishapp.com/rspec/rspec-rails/v/3-9/docs/mailer-specs/mailer-spec
context 'when using RSpec mailer examples' do
subject(:mail) { described_class.signup }
it 'renders the headers' do
expect(mail.subject).to eq('Signup')
expect(mail.to).to eq(['[email protected]'])
expect(mail.from).to eq(['[email protected]'])
end
it 'renders the body' do
expect(mail.body.encoded).to match('Hi')
end
it 'sends the mail' do
expect { mail.deliver_now }.to change { ActionMailer::Base.deliveries.count }
end
end
# @see: https://github.com/mikel/mail#using-mail-with-testing-or-specing-libraries
context 'when using Mail::Matchers' do
subject(:mail) { described_class.signup.deliver_now }
it { is_expected.to have_sent_email }
it { is_expected.to have_sent_email.from('[email protected]') }
it { is_expected.to have_sent_email.to('[email protected]') }
it { is_expected.to have_sent_email.with_subject('Signup') }
it { is_expected.to have_sent_email.with_body('Hi') }
end
end
end
メール送信後のマッチャが全て have_sent_email
に集約されているのがわかりますね。
ここで紹介したもの以外にも、添付ファイルに対するマッチャなど、メールのテストに必要なものが一通り揃っているので、ぜひドキュメントを確認して使ってみてください。
https://github.com/mikel/mail#using-mail-with-testing-or-specing-libraries
最後に
ここまで読んで、実際に自分で試してみたいと思われた方のために、動くサンプルコードを Gist で公開しています。
https://gist.github.com/tomohiro/dfa7362cd066dd87f25f40bdd6856513
余談
個人的には --format documentation
で出力したときの表現が冗長に感じています。
参考資料
Author And Source
この問題について(【Rails】ActionMailer のテストで Mail::Matchers を使う), 我々は、より多くの情報をここで見つけました https://qiita.com/Tomohiro/items/c45adb704a87f2c7b519著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .