sajad torkamani

Configure ActionMailer for tests

By default, the line config.action_mailer.delivery_method = :test in config/environments/test.rb configures ActionMailer not to deliver emails but to accumulate them in the ActionMailer::Base.deliveries array. Make sure you don’t change this behaviour.

To make your mailer tests read better, consider adding the following helper in a spec support file:

def sent_emails
  ActionMailer::Base.deliveries
end

Test that the email content is correct

You want to write a unit test that checks:

  • Email sender is correct
  • Email recipient is correct
  • Email subject is correct
  • Email body is correct

Something like this (spec/mailers/reminder_mailer_spec.rb):

# frozen_string_literal: true

require 'rails_helper'

RSpec.describe ReminderMailer, type: :mailer do
  describe 'reminder_email' do
    it 'creates the correct email' do
      reminder = create(:reminder, :with_notes)

      email = described_class.with(reminder:).reminder_email

      expect(email.from).to eq [Rails.configuration.from_email]
      expect(email.to).to eq [reminder.user.email]
      expect(email.subject).to eq reminder.name
      [email.html_part.body, email.text_part.body].each do |email_body|
        reminder.notes.each do |note|
          expect(email_body).to include note.content.to_plain_text
        end
      end
    end
  end
end

Test that email is sent at the right time

You want to test that the email is enqueued or sent when expected. Usually, you’ll enqueue or send emails in controllers or jobs.

Something like this (spec/jobs/send_reminders_job_spec.rb):

# frozen_string_literal: true

require 'rails_helper'

RSpec.describe SendRemindersJob, type: :job do
  it 'sends a reminder email to users who have a reminder configured' do
    jim = create(:user)
    jim_reminder = create(:reminder, :with_notes, user: jim)
    _bob = create(:user)

    described_class.perform_now
    emails_sent = ActionMailer::Base.deliveries

    expect(emails_sent.count).to eq 1
    expect(emails_sent.map(&:to).flatten).to eq [jim.email]
    expect(emails_sent.map(&:subject)).to eq [jim_reminder.name]
  end

  it "doesn't send a reminder email to users who have reminders configured but have not notes" do
    jim = create(:user)
    jim_reminder = create(:reminder, :with_notes, user: jim)
    bob = create(:user)
    _bob_reminder = create(:reminder, :without_notes, user: bob)

    described_class.perform_now
    emails_sent = ActionMailer::Base.deliveries

    expect(emails_sent.map(&:to).flatten).to eq [jim.email]
    expect(emails_sent.map(&:subject)).to eq [jim_reminder.name]
  end
end

Sources