井原(@ihara2525)です。
RSpecでActionMailerのdeliver_later!が呼び出されることをテストするコードを書いてみます。
コメントがあったときにメールで通知するサービスオブジェクトをつくり、それは中でActionMailerのdeliver_later!等を呼び出しているとします。こんな感じ。
app/services/comment_notification.rb
class CommentNotification def initialize(comment) CommentNotificationMailer.notify(comment).deliver_later! end end
このサービスオブジェクトをnewしたときに、これらのメソッドが呼び出されることを保証するRSpecのテストを書こうとしてみました。
spec/services/comment_notification_spec.rb
require 'rails_helper' RSpec.describe CommentNotification do describe 'new' do let(:blog) { FactoryGirl.build_stubbed(:blog) } let(:comment) { FactoryGirl.build_stubbed(:comment, commentable: blog) } let(:mailer) { double('mailer', deliver_later!: true) } it 'calls mailer methods' do expect(CommentNotificationMailer).to receive(:notify).with(comment).and_return(mailer) expect(mailer).to receive(:deliver_later!) CommentNotification.new(comment) end end end
テストの中身を見てみると、
expect(CommentNotificationMailer).to receive(:notify).with(comment).and_return(mailer)
で、CommentNotificationMailerのnotifyメソッドがcommentを引数に呼び出されてmailerを返し、
expect(mailer).to receive(:deliver_later!)
で、そのmailerがdeliver_later!を呼び出されることをテストする、みたいな。
expect(CommentNotificationMailer).to recieve_message_chain(:notify, :deliver_later!)
とメソッドチェインのテストを書くこともできたのですが、commentを引数にnotifyが呼び出されていることをテストしておきたかったので、このようなかたちになりました。
もっと良いやり方があるのかな〜。