ActionMailer のメール送信テストを RSpec で行う

ActionMailer のテスト方法を調べてテストを書いたので、まとめておきます。RailsGuides の ActionMailer と Testing Your Mailers のページに目を通しておくと、理解しやすいかと思います。

Action Mailer Basics — Ruby on Rails Guides
A Guide to Testing Rails Applications — Ruby on Rails Guides

スポンサーリンク

— 環境 —
rails-4.0.1
rspec-rails-2.14.0
capybara-2.2.0

Action Mailer のテストで確認すべき項目

RailsGuides の Testing Your Mailers で以下のように書いてある。

The goals of testing your mailer classes are to ensure that:

・emails are being processed (created and sent)
・the email content is correct (subject, sender, body, etc)
・the right emails are being sent at the right times

以下、翻訳。

Mailer クラスのテストの目的は、以下を確かめること。

1. Eメールが正しく処理されること。(Eメールの作成と送信)
2. Eメールの内容が正しいこと。(表題、送信者のアドレス、本文など)
3. Eメールが正しい時間に送信されること。

読み進めると、unit tests および functional tests で Mailer をテストすると説明してあります。

unit tests:
単体でテストを行い、入力値と出力値を比較して確認する。上記の 1, 2 の項目をテスト。

functional tests:
Mailer を使うコントローラーやモデルが Mailer を正しく操作しているかテストする。正しいEメールが正しい時間に送られたかをテストする。上記 3 の項目をテスト。

Unit Testing

ActionMailer::Base.deliveries に送信済みのメール(メールのオブジェクト)が配列で格納されます。

Action Mailer Basics — Ruby on Rails Guides

Unit テストでは次を確認する。

・Eメール を deliver(送信)した後に、ActionMailer::Base.deliveries が空でないことを確認。
・Eメールの from, to, subject, body などの内容を確認。

以下、RailsGuides の Testing Your Mailers から引用のサンプルコードです。

environments/test.rb で次のように設定しておくと、Mailer のテストで実際にEメールを送信せずにテストモードで動作します。

config/environments/test.rb

ActionMailer::Base.deliveries 配列は、ActionMailer::TestCase でのみ自動でリセットされる。それ以外のテストでリセットしたい場合は、明示的に ActionMailer::Base.deliveries.clear を呼び出してリセットする必要があります。

Functional Testing

functional tests では、Mailer の deliver メソッドを呼び出し以下を確認する。

・Eメールが正しく delivery list に追加されたかを確認。
・正しいビジネスロジックでEメールが送信されるかを確認。
・正しい時間に送信されるかを確認。

以下、RailsGuides の Testing Your Mailers から引用のサンプルコードです。

ActionMailer::Base.deliveries.size → 送信済みメールの数
ActionMailer::Base.deliveries.last → 最後に送信されたEメール

では前置きが長くなりましたが、以降が自分で書いた RSpec で ActionMailer をテストするコードです。

RSpec で ActionMailer の Unit Test

spec/mailers/user_mailer_spec.rb

メールを作成して送信する前と、送信した後でテストを行っています。送信前は、ActionMailer::Base.deliveries が空であることをチェック、送信後は 1 になっていることを確認しています。

あと、なぜか mail.body が空になりました。 mail.body.encoded だと取得できるのですが、Base64 でエンコードされた文字列なので、デコードする処理を行っています。こうしないと、it “renders the body” do の正規表現マッチャーが使えなかったので。

APP_CONFIG[’email’][‘from’] については以下。

Rails でアプリ固有の設定情報や定数を定義する | EasyRamble

RSpec で ActionMailer の Functional Test

RailsGuides では、Functional test は UserControllerTest に書いてあるので、RSpec の場合もそれに倣うと spec/controllers/user_controller_spec.rb に書けば良いかと思います。私はできるだけ RequestSpec にテストを書くようにしているので、spec/requests/user_regsitration_pages_spec.rb に Capybara でサインアップフォームを埋める動作からテストを書きました。

新規ユーザー登録完了時に、確認メールを送信する UserMailer#registration_confirmation(user) メソッドが実装されているものとします。

Rails4 の ActionMailer でメール送信 | EasyRamble
Deviseでユーザー登録完了時にウェルカムメールを送信する | EasyRamble

spec/requests/user_regsitration_pages_spec.rb

Capybara でフォーム入力して ActionMailer 用の RequestSpec を書きました。こんな感じで RSpec で ActionMailer のテストを行えます。他、RSpec での ActionMailer のテストは以下のページが参考になりました。

スポンサーリンク
私は Rails のテストフレームワークには RSpec を使っています。サーバーのテスト用に Serverspec もおすすめです。
スポンサーリンク
 
Twitterを使っていますのでフォローお願いたします!ブログの更新情報もつぶやいてます^^
(英語学習用)

Leave Your Message!