Small Rspec revelations, ActionMailer

At the office we are getting more and more serious about RSpec . Today we ran into two things we had not done so far. Specing an ActionMailer and a module. The Rails Way only covered Test::Unit and that looked dreadful. Way to much code. I still think I should be coding applications not tests. A quick google turned up not so much, nor did the RSpec site help. Fortunately someone on the RSpec mailinglist brought the subject up. With that I knew enough to get the tests working.


before(:each) do
ActionMailer::Base.delivery_method = :test
ActionMailer::Base.perform_deliveries = true
ActionMailer::Base.deliveries = []
end

This before block set the method for delivery method to :test. Normally it default to :smtp and an other possibility is :sendmail. The second directive tells ActionMailer to actually send the emails(who would have guessed?). The deliveries array keeps track of every email sent.

Now you can just send your email as you usually would:


mail = Notifications.deliver_some_random_email("name")
ActionMailer::Base.deliveries.size.should == 1
mail.body.should =~ /name/

Rock on RSpec.

Tags: ,

7 Responses to “Small Rspec revelations, ActionMailer”

  1. Ariejan Says:

    Awesome! Thanks!

  2. Dan Garland Says:

    Thanks for this it worked well for me.

    I opted to put
    ActionMailer::Base.delivery_method = :test

    in my environment though.

    Cheers,

  3. Marcelo Silveira Says:

    Helped a lot. Thanks!

  4. Simple Email Form with ActionMailer Says:

    […] In test-driven style (thanks to rubytutorials.net), here’s a spec for we’ll make work (at least the sending mail part of it). Note that […]

  5. ahabman Says:

    Perfect. That’s exactly what I needed.

  6. Amit Says:

    Hi i am testing email through rspec.I followed your suggestions but some problem occured.
    This is the whole scenario:
    What i want to do is when my user is created it should send mail to for activation.
    This is the code under user_spec.rb
    require File.expand_path(File.dirname(__FILE__) + ‘/../spec_helper’)
    #require ‘rasta/fixture/rasta_fixture’
    #require ‘fastercsv’

    def valid_user_attributes
    {
    :email => “testing@joshsoftware.com”,
    :login => “test”,
    :password => “test123″,
    :password_confirmation => “test123″,
    :role_id => 1
    }
    end

    describe User do
    before(:each) do
    @user = User.create
    ActionMailer::Base.delivery_method = :test
    ActionMailer::Base.perform_deliveries = true
    ActionMailer::Base.deliveries = []
    end

    fixtures :users

    context “User” do
    it “should be create if all the credentials are provided” do
    @user.attributes = valid_user_attributes
    mail = Notifier.signup_notification(”user_1″)
    ActionMailer::Base.deliveries.size.should == 1
    mail.body.should =~ /Please signup/
    @user.should be_valid
    @user.save
    end

    Now here Notifier ia another model which contains signup_ notification method.
    Is it the case that i would need to test that in notifier spec or is it possible to get notifier model in user like require ‘notifier.rb’
    Please suggest

  7. admin Says:

    You have to spec a notifier (instance of ActionMailer) seperately. And it took me a long time to figure out. A spec would look something like this:

    describe Notifications, :type => :helper do #setting type is necessary
    before(:each) do
    ActionMailer::Base.delivery_method = :test
    ActionMailer::Base.perform_deliveries = true
    ActionMailer::Base.deliveries = []
    end

    it “should sent a nice email with the analyses to the user” do
    analysis_observer = AnalysisObserver.instance
    analysis_observer.stub!(:after_create)
    mail = Notifications.deliver_analyses_to_user “somegmail@gmail.com”, Factory(:temporary_user, :analyses => [Factory(:analysis)])
    ActionMailer::Base.deliveries.size.should == 1
    mail.body.should have_tag(”img”, 3)
    mail.body.should have_tag(”table”)
    end

    Hope that helps!

Leave a Reply