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
end
end
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?
Thanks,
Dmitry
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 @profile.name, 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 => “user@example.com”)
@applicant = stub(:full_name => “john doe”, :user => @user)
@assessment_url = “http://www.example.com”
@email = Mailer.create_job_application_submitted(@applicant, @assessment_url)
end
it “addresses the email from the support address” do
@email.from.should == [“support@wingnut.com”]
end
it “addresses the email to the given user” do
@email.to.should == [@user.email_address]
end
it “sets the subject” do
@email.subject.should == “#{@applicant.full_name.titleize} - Job application submitted”
end
it “includes the applicant name in the body” do
@email.body.should match(/#{@applicant.full_name.titleize}/)
end
it “includes the applicant’s assessment link in the body” do
@email.body.should match(/#{@assessment_url}/)
end
end
Hope that helps somehow.
Also, the Rails Guides site has some content on testing mailers: http://guides.rails.info/testing_rails_applications.html#_testing_your_mailers .
Regards,
Craig
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)
end
should "contain key pair :bar => @bar" do
assert_equal @bar, @body_hash[:bar]
end
end
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.
Dmitry