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.
March 11th, 2009 at 1:17 pm
Awesome! Thanks!
May 22nd, 2009 at 11:06 am
Thanks for this it worked well for me.
I opted to put
ActionMailer::Base.delivery_method = :test
in my environment though.
Cheers,
October 29th, 2009 at 8:51 pm
Helped a lot. Thanks!
November 18th, 2009 at 7:33 am
[…] 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 […]
November 24th, 2009 at 6:48 pm
Perfect. That’s exactly what I needed.
January 22nd, 2010 at 7:57 am
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
January 22nd, 2010 at 8:37 am
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!