The delivery_matchers
gem is an open-sourced Ruby gem written by General Assembly that exposes an
RSpec custom matcher for ActionMailer’s deliver_later method.
Motivation
One of our products at GA contained a considerable amount of logic to determine
when to send certain transactional emails to different subsets of students.
We wanted to ensure this code had bulletproof test coverage. Inspecting the
in-memory ActiveJob queue let us test our delivery logic, but it also allowed a
lot of low-level details to leak into our tests, making them harder to read.
For example, we had some tests that looked like this:
it 'sends the "project submitted" email' do
post :create, params
expect(enqueued_jobs.first[:args]).to include("ProjectMailer", "project_submitted", "deliver_now")
expect(enqueued_jobs.first[:args].last.values).to include(project.to_global_id.to_s)
end
as well as some RSpec configuration to ensure a clean environment for each test:
config.around :each do |example|
ActionMailer::Base.deliveries.clear
example.run
ActionMailer::Base.deliveries.clear
end
As our testing requirements grew (eg. asserting when exactly an email is sent
when queued with deliver_later), our test code grew unruly.
We refactored and extracted this testing logic into the delivery_matchers gem
to keep our test code maintainable.
Usage
Install the gem by including in your Gemfile:
gem 'delivery_matchers'
Include the matchers in your RSpec configuration with:
RSpec.configure do |config|
config.include DeliveryMatchers
end
Now, mail delivery can be asserted as follows:
it 'sends the "project submitted" email' do
post :create, params
expect(ProjectMailer).to deliver_later(:project_submitted).with(saved)
end
Delivery options that control when emails are delivered can be tested like so:
# When email is scheduled for a particular date, like Christmas
expect(email).to be_delivered on: expected_date
# When email is scheduled for delivery after an interval of time
expect(email).to be_delivered in: 2.days
You can also test that the delivery job was scheduled in a particular queue:
expect(email).to be_delivered via_queue: 'priority'
This gem enabled us to greatly simplify the mailer test code in our
applications. We hope you’ll enjoy it!
Useful links