Creating instance of ActionMailer for testing

Hi all,
I am writing an action mailer test and am trying to snatch contents
of the @body hash provided for the template for testing. Specifically,
my plan is to do something like:

FooMailer.class_eval do
  attr_accessor :original_body
  def render_message method, body
    self.original_body = body
    super method, body

and then test that a FooMailer instance has its original_body setup
correctly (together with to, from and other headers).

However, I noticed that ActionMailer::Base goes out of its way to
prevent instantiating mailer objects. Why does it do that?


PS I realize that usual approach is just use pattern matching for the
resulting TMail body. However such method seems to strongly couple the
test to the email body template (e.g. I may setup the body[:profile]
but the email resulting body may only contain the, so
the test has to know that the template renders just the name and
change if the template changes)

Email templates change very rarely on my project, so I don’t mind the usual approach of matching the body against a few patterns. And, it’s easy to do. Anyway, here’s an example spec of a mailer on my current project:

describe Mailer, “job application submitted” do

before(:each) do
@user = stub(:full_name => “Jane Roe”, :email_address => “”)
@applicant = stub(:full_name => “john doe”, :user => @user)
@assessment_url = “
@email = Mailer.create_job_application_submitted(@applicant, @assessment_url)

it “addresses the email from the support address” do
@email.from.should == [“”]

it “addresses the email to the given user” do == [@user.email_address]

it “sets the subject” do
@email.subject.should == “#{@applicant.full_name.titleize} - Job application submitted”

it “includes the applicant name in the body” do
@email.body.should match(/#{@applicant.full_name.titleize}/)

it “includes the applicant’s assessment link in the body” do
@email.body.should match(/#{@assessment_url}/)


Hope that helps somehow.

Also, the Rails Guides site has some content on testing mailers: .


Thanks for the reply! Your solution works, but it is pretty much same
as just doing assert_matches.
After some thinking I realized that I can just stub out the
render_message of the ActionMailer::Base class:

context "Email body hash" do
   setup do
     @bar = Bar.create!
     FooMailer.any_instance.stubs(:render_message).with { |template,
body> @body_hash = body}.returns(:email_body)
     @email = FooMailler.create_send_foo(@bar)

   should "contain key pair :bar => @bar" do
     assert_equal @bar, @body_hash[:bar]

And that seems to do the trick.
I am still quite curious as to why ActionMailer::Base is so set
against having instances, but at least it works.