April 3, 2015

Quick tip: Testing email delivery with `deliver_later`

Scenario

You want to test that email is send after some action.

describe UsersController do
  describe '#create' do
    before do
      ActionMailer::Base.deliveries = []
    end

    it 'sends welcome email to the user' do
      expect do
        post :create, user: { email: 'john.doe@example.com', password: 'password' }
      end.to change(ActionMailer::Base.deliveries, :count).by(1)
    end
  end
end

Problem

You use #deliver_later which doesn't send emails immediately but it schedules them for the later delivery.

UserMailer.user_signed_up(@user).deliver_later

Solution

Monkey patch #deliver_later in the test environment to send the email immediately.

# spec/support/message_delivery.rb
class ActionMailer::MessageDelivery
  def deliver_later
    deliver_now
  end
end

Conclusion

There are different ways how to solve this. For example for Sidekiq you can use the inline mode. But above mentioned solution is the same for all background processing systems and you do not need to schedule (and execute) any background jobs in the test environment at all.

Hey there!

My name is Patrik Bóna and I am the only programmer at Memberful. This blog is kind of dead, but I just started my own Ruby on Rails screencast. Follow me on Twitter if you want to be notified about my newest videos.