How to test emails in Rails
25 April 2022 (Updated 15 May 2022)
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
Tagged:
Rails testing
Thanks for your comment 🙏. Once it's approved, it will appear here.
Leave a comment