The ActionMailer module was reconstructed in Rails 3 and the way to test it is a little different. Now, the mailers has a itself subdirectory (on app/) and it’s look like the controllers.
Assuming we’ve a mailer to send same information:
class Notifier < ActionMailer::Base
default :from => 'noreply@company.com'
def instructions(user)
@name = user.name
@confirmation_url = confirmation_url(user)
mail :to => user.email, :subject => 'Instructions'
end
end
To send an email through a method from User class:
class User
def send_instructions
Notifier.instructions(self).deliver
end
end
Before test it, make sure the config/environments/test.rb file is configured as follows:
AppName::Application.configure do config.action_mailer.delivery_method = :test end
This ensures that emails won’t send, but store on ActionMailer::Base.deliveries array. After, just create the tests:
spec/models/user_spec.rb
require 'spec_helper'
describe User do
before :each do
@user = User.make
end
it "sends a e-mail" do
@user.send_instructions
ActionMailer::Base.deliveries.last.to.should == [@user.email]
end
end
spec/mailers/notifier_spec.rb
require 'spec_helper'
describe Notifier do
describe 'instructions' do
let(:user) { mock_model(User, :name => 'Lucas', :email => 'lucas@email.com') }
let(:mail) { Notifier.instructions(user) }
#ensure that the subject is correct
it 'renders the subject' do
mail.subject.should == 'Instructions'
end
#ensure that the receiver is correct
it 'renders the receiver email' do
mail.to.should == [user.email]
end
#ensure that the sender is correct
it 'renders the sender email' do
mail.from.should == ['noreply@empresa.com']
end
#ensure that the @name variable appears in the email body
it 'assigns @name' do
mail.body.encoded.should match(user.name)
end
#ensure that the @confirmation_url variable appears in the email body
it 'assigns @confirmation_url' do
mail.body.encoded.should match("http://aplication_url/#{user.id}/confirmation")
end
end
end
In conclusion, Rails 3 allows you to create very comprehensive tests for mailers without using plugins or gems to facilitate such tests, which were common in Rails 2.