sublim.nl

1.5M ratings
277k ratings

See, that’s what the app is perfect for.

Sounds perfect Wahhhh, I don’t wanna
ga-engineering-blog

Delivery Matchers

ga-engineering

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