Testing Emails and ActiveJob#deliver_later in RSpec feature tests
I got tripped up by this the other day - I was writing feature specs around resetting passwords, and my PasswordReset
interactor used ActiveJob
to send the password reset email asynchronously.
Before ActiveJob
you could just access ActionMailer::Base.deliveries
and get at the message that had been generated, but that wasn’t working. After a bit of searching and some failed attempts at other approaches, I figured out what needed to be done.
Since ActiveJob
and ActionMailer
’s .deliver_later
queue up jobs to process later, you need to actually process the queue before you can access the email. To do this you need to first include ActiveJob::TestHelper
in your feature spec. This gives access to a few methods, but the one that we need is perform_enqueued_jobs
.
perform_enqueued_jobs
takes a block and performs any jobs in the ActiveJob
queue after the block has completed. We pass the click_button "Reset Password"
line in, and when that button is clicked the controller for password resets handles the process of generating the password reset email and putting it in to the queue. Without calling perform_enqueued_jobs
, that’s where it would sit, unprocessed and unavailable to our tests.
Since the queue is processed, the email is now available for us to access. In this case I am using the capybara-email gem to access the email and follow the link to it. From there everything continues as any normal feature spec would.
Notes
One weird thing that I encountered while doing this was that while including ActiveJob::TestHelper
at the top of the spec got it to pass, it broke a few other specs that were directly checking ActiveJob::Base.queue_adapter.enqueued_jobs
started to break because ActiveJob::Base.queue_adapter
was nil.
I haven’t investigated this much so far, but moving include "ActiveJob::TestHelper"
to rails_helper.rb
fixed it, so I’ve left it at that for now.