Clearing out ActionMailer::Base.deliveries after RSpec test
Solution 1
RSpec.describe UserMailer do
before do
# ActionMailer::Base.deliveries is a regular array
ActionMailer::Base.deliveries = []
# or use ActionMailer::Base.deliveries.clear
end
it "sends welcome email" do
user = create(:user)
UserMailer.welcome_email(user).deliver_now
expect(ActionMailer::Base.deliveries).to be_present
end
end
Solution 2
You can clear the deliveries after each test quite easily, adding this into your spec_helper.rb.
RSpec.configure do |config|
config.before { ActionMailer::Base.deliveries.clear }
end
I'd suggest reading my article about the correct emails configuration in Rails where I talk also about testing them correctly.
Solution 3
As Andy Lindeman points out, clearing the deliveries is done automatically for mailer tests. However, for other types, simply add , :type => :mailer
to the wrapping block to force the same behavior.
describe "tests that send emails", type: :mailer do
# some tests
end
Remy Vanherweghem
Software developer at Google, Irvine Blog Google+ Twitter
Updated on June 05, 2022Comments
-
Remy Vanherweghem almost 2 years
I have the following RSpec test for my UserMailer class:
require "spec_helper" describe UserMailer do it "should send welcome emails" do ActionMailer::Base.deliveries.should be_empty user = Factory(:user) UserMailer.welcome_email(user).deliver ActionMailer::Base.deliveries.should_not be_empty end end
This test passed the first time, but failed the second time I ran it. After doing a little bit of debugging, it appears that the 1st test added an item to the ActionMailer::Base.deliveries array and that item never got cleared out. That causes the first line in the test to fail since the array is not empty.
What's the best way to clear out the ActionMailer::Base.deliveries array after an RSpec test?
-
Luke Francl about 12 yearsTo avoid repeating this, you can put it in the config block of spec_helper.rb:
config.before(:each) { ActionMailer::Base.deliveries.clear }
-
Andy Lindeman over 11 yearsThis should not be needed as RSpec mailer specs should be setup to clear the deliveries array automatically. See github.com/rspec/rspec-rails/issues/661 for details.
-
froderik over 10 yearsIt is supposed to work for mailer specs but not for request specs - then you need to clear it yourself somehow. Me? I am going for the Luke Francl method.
-
kasia over 9 yearsThanks for the tip! This feels like a much cleaner approach to me. Works with Rails 4.1 and Rspec 3.1.
-
karlingen about 9 yearsYup. this was the issue I had. I forgot to add
type: :mailer
. Thanks d_rail! -
Kevin Walsh about 9 yearsThis seems like the clearest solution so far. For projects using email-spec, consider calling
reset_mailer
in the before block in place ofActionMailer::Base.deliveries.clear
asreset_mailer
does a little extra work that may be helpful.RSpec.configure do |config| config.before(:each) { reset_mailer } end
-
C.J. almost 9 yearsThis seems fundamentally fragile to me. Decorating test cases with special flags to make them behave in ways that are not obvious. I prefer the other answers.
-
sevenseacat about 8 yearsadding a "mailer" tag to a test that is not specifically a mailer unit test seems broken. I'd rather go for one of the other approaches.