Search code examples
ruby-on-railsactionmailerruby-on-rails-5.2

How to test emails that are set to deliver later


I can't figure out how to get the syntax to work for asserting that an email has been enqueued properly. Specifically, how do you pass in the arguments to the mailer when the argument is an object?

For example, if you want to pass in a contact object to the example from the documentation:

  assert_enqueued_email_with ContactMailer, :welcome, @contact do
    ContactMailer.welcome(@contact).deliver_later
  end

  assert_enqueued_email_with ContactMailer, :welcome, args: @contact do
    ContactMailer.welcome.deliver_later
  end

  assert_enqueued_email_with ContactMailer, :welcome, [@contact] do
    ContactMailer.welcome.deliver_later
  end

None of these appear to work. If you look at the actual enqueued job, the object looks like this:

{:job=>ActionMailer::DeliveryJob, :args=>["ContactMailer", "welcome", "deliver_now", {"_aj_globalid"=>"gid://app_name/Contact/1015983224"}], :queue=>"mailers"}

Any help is appreciated!


Solution

  • I know this is probably too late to help you, but I ran across the same issue recently, so hopefully this workaround will help the next person. Under the hood, assert_enqueued_email_with just uses assert_enqueued_with, and we can use it directly to create a test that will find the enqueued email like so.

    assert_enqueued_with(job: ContactMailer.delivery_job, args: ['ContactMailer', 'welcome', 'deliver_now', @contact], queue: 'mailers')
    

    The only difference between this test, and what assert_enqueued_email_with generates is @contact isn't wrapped in an extra array.

    Edit: I wanted to come back in to mention that I only encountered this error during the middle of an update from Rails 5.2 to Rails 6.0. Once I got further into the update this went away and assert_enqueued_with worked as expected, while the previous workaround using assert_enqueued_with no longer matched. Specifically it was after setting delivery_job to the new default.

    Rails.application.config.action_mailer.delivery_job = "ActionMailer::MailDeliveryJob"