Testing ActionMailer with RSpec

Here’s my approach to testing ActionMailer email. I want to test for two things: that the email will contain the correct content and that the email will be delivered. I also want to make sure that the email looks properly formatted, and for this I use the gem letter_opener

Testing the content is easy. Let’s take the blog Post example where we would want the author to receive an email when someone writes a comment on their post. We have two models Post and Comment, where posts have many comments and a comment belongs to a post. And we also have our mailer object with a function called send_comment_notification, which takes a comment as an argument and sends it to the author. And let’s say the requirement for the email should be that it include the title of the post, the name of the commenter and the comment.

Here’s what my RSpec test would look like:

describe PostMailer do
  describe '#send_comment_notification' do
    before(:each) do
      @comment = Factory(:comment)
      @mail = PostMailer.send_comment_notification(@comment)
    end

    it 'should have the title of the post' do
      @mail.encoded.should include(@comment.post.title)
    end

    it 'should contain the name of the person who commented on the post' do
      @mail.encoded.should include(@comment.name)
    end

    it 'should contain the comment' do
      @mail.encoded.should include(@comment.body)
    end

    it 'should send the email' do
      @mail.deliver!
      ActionMailer::Base.deliveries.size.should == 1
    end
  end
end

Everything but the last step should be self explanatory. The last step uses the deliveries array to test against. In your test environment ActionMailer is set like this:

...
config.action_mailer.delivery_method = :test
...

Which sends the messages to the deliveries array instead of sending the messages out into the real world.

In case that doesn’t work, you can manually configure this:

ActionMailer::Base.delivery_method = :test
ActionMailer::Base.perform_deliveries = true
ActionMailer::Base.deliveries = []

which you can put in a method in spec_helper or have it always be configured.

So, another thing I wanted to touch on, since I’m talking about email testing in Rails is a gem called letter_opener. Just place it in your Gemfile under your development group. This gem will open up the email in a new window when it gets delivered so you can see that it is formatted correctly without having to send it to yourself. Needless to say, really handy tool to have. The only thing you need to do in order to get letter_opener to work is to change:

...
config.action_mailer.delivery_method = :test
...

in development.rb to:

...
config.action_mailer.delivery_method = :letter_opener
...