Last Updated: February 25, 2016
·
7.56K
· gurix

Testing ActionMailer "deliver_later" with rspec

I wanted to test sending some profile information via mail. The reason was that I switched from inline to background processing via ActiveJobs.

As we are in a test environment we don't want to send emails so we set the delivery method in test.rb to :test:

config.action_mailer.delivery_method = :test

First I had to include ActiveJob::TestHelper in my feature test. This is giving you various methods to test queues.

To have a clean test environment I cleaned first all enqueued jobs to avoid conflicts between tests.

before { clear_enqueued_jobs }

The test:

scenario "a user sends his profile to a conusltant" do
    sign_in_as(user)

    visit main_app.new_send_profile_path

    # Ensure user can not fill in an invalid email 
    fill_in "Consultant E-Mail", with: "abc"

    # No job is enqued, user has to fill in a correct email
    expect { click_button "Send profile"}.to change { enqueued_jobs.size }.by(0)

    fill_in "Consultant E-Mail", with: "hans.muster@awesome-consulting.com"

    expect { click_button "Send profile" }.to change { enqueued_jobs.size }.by(1)

    mail = perform_enqueued_jobs { ActionMailer::DeliveryJob.perform_now(*enqueued_jobs.first[:args]) }

    expect(ProfileMailer.deliveries.count).to eq 1

    expect(mail.subject).to have_content "Awesome survey"
  end

The crucial part was to perform the enqueued job to get a proper email. The trick is to perform the job by hand:

mail = perform_enqueued_jobs { ActionMailer::DeliveryJob.perform_now(*enqueued_jobs.first[:args]) }

This is giving you the mail object and the deliveries array as when you send inline.