Question

I am using rspec-rails and I want to test that my mailer is rendering the correct view template.

describe MyMailer do
  describe '#notify_customer' do
    it 'sends a notification' do
      # fire
      email = MyMailer.notify_customer.deliver

      expect(ActionMailer::Base.deliveries).not_to be_empty
      expect(email.from).to include "cs@mycompany.com"

      # I would like to test here something like
      # ***** HOW ? *****
      expect(template_path).to eq("mailers/my_mailer/notify_customer")
    end
  end
end

Is this a valid approach? Or shall I do something completely different to that?

Update

MyMailer#notify_customer might have some logic (e.g. depending on the locale of the customer) to choose different template under different circumstances. It is more or less similar problem with controllers rendering different view templates under different circumstances. With RSpec you can write

expect(response).to render_template "....." 

and it works. I am looking for something similar for the mailers.

Was it helpful?

Solution

I think this is a step closer to the answer above, since it does test for implicit templates.

    # IMPORTANT!
    # must copy https://gitlab.com/gitlab-org/gitlab/-/blob/master/spec/support/helpers/next_instance_of.rb
    it 'renders foo_mail' do
      allow_next_instance_of(described_class) do |mailer|
        allow(mailer).to receive(:render_to_body).and_wrap_original do |m, options|
          expect(options[:template]).to eq('foo_mail')

          m.call(options)
        end
      end

      body = subject.body.encoded
    end

OTHER TIPS

OK, I understand what you're trying to achieve now.

You should be able to test which template is called by setting expectations on your mailer for the mail method having been called with particular arguments.

Try this in your test:

MyMailer.should_receive(:mail).with(hash_including(:template => 'expected_template'))
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top