config.action_mailer.delivery_method = :test
Compare to the line in config/environments/development.rb
config.action_mailer.delivery_method = :smtp
Setting this to test stops e-mails being sent, and instead they are sent to an array, ActionMailer::Base.deliveries. This array is reset before each test, by the way.
Here is a simple mailer to test.
class Notifier < ActionMailer::Base default :from => "DB@mysite.com" add_template_helper(ApplicationHelper) # Sets up an e-mail for notifying the user to activate his account. def signup_notification user @name = user.username @login = user.login @url = "http://mysite.com/activate/#{user.activation_code}" mail :to => user.email, :subject => 'Activate your account' end def page_error(err, request) @err = err @request = request mail :to => 'admin@mysite.com', :subject => 'Page error' end end
In your controller, you might invoke the first like this:
Notifier.signup_notification(@user).deliver
In the test, you will need to break that up, so you can examine the mail object.
class NotifierTest < ActionMailer::TestCase test "signup_notification" do # Create a mock user user = TestUser.new 'tester', 'tester@nowhere.com' # Invoke the mailer method mail = Notifier.signup_notification user # Deliver the mail mail.deliver # Check the mail got sent assert !ActionMailer::Base.deliveries.empty? # Check it is the right mail assert_equal 'Activate your account', mail.subject assert_equal ["tester@nowhere.com"], mail.to assert_equal ["DB@mysite.com"], mail.from assert_match "Visit this url to activate your account", mail.body.encoded end end
Here is the TestUser definition.
class TestUser attr_reader :username, :email, :login def initialize username, email @username = username @email = email @login = username.gsub ' ', '' end def activation_code; "abcd"; end end
The second method in the mailer above is for sending error reports to the administrator. Here is a method that generates an error, and sends that to the mailer:
test "page_error" do request = TestRequest.new begin raise "A test error" rescue Exception => err mail = Notifier.page_error(err, request) mail.deliver assert !ActionMailer::Base.deliveries.empty? assert_equal "Page error", mail.subject assert_equal ["admin@mysite.com"], mail.to assert_equal ["DB@mysite.com"], mail.from assert_match "error encountered!", mail.body.encoded end end
Here is the TestRequest definition; it simply returns the string "good" if the method name is recognised - that is enough for the mailer to wok with, and will still highlight any mistyped or made-up method names.
class TestRequest # Returns the string "good" if the method is recognised def method_missing method, *args return "good" if [:fullpath, :request_method, :query_parameters, :request_parameters, :referer].include? method super end endend