Search code examples
ruby-on-railsrubyrspecmailer

Best way to test a mailer with arguments


I have a mailer that passes an argument like so:

AnimalMailer.daily_message(owner).deliver_later

The method looks like this:

AnimalMailer

class AnimalMailer < ApplicationMailer

  def daily_message(owner)
     mail(
      to: "#{user.name}",
      subject: "test",
      content_type: "text/html",
      date: Time.now.in_time_zone("Mountain Time (US & Canada)")
    )
  end
end

I'm new to writing specs and was wondering how should I pass the owner to the method and test it. I currently have this set up:

require "rails_helper"

RSpec.describe AnimalMailer, type: :mailer do
  
  describe "monthly_animal_message" do
    let(:user) { create(:user, :admin) }

    it "renders the headers" do
      expect(mail.subject).to eq("test")
      expect(mail.to).to eq(user.name)
    end
  end
end

Solution

  • Specs generally follow a three-step flow 1) set up, 2) invoke, 3) expect. This applies for unit testing mailers like anything else. The invocation and parameters are the same in the test as for general use, so in your case:

    RSpec.describe AnimalMailer, type: :mailer do  
      describe "monthly_campaign_report" do
        let(:user) { create(:user, :admin) }
        let(:mail) { described_class.daily_message(user) }  # invocation
    
        it 'renders the headers' do
          expect(mail.subject).to eq('test')
          expect(mail.to).to eq(user.name)
        end
    
        it 'renders the body' do
          # whatever
        end
      end
    end
    

    Note that since the describe is the class name being tested, you can use described_class from there to refer back to the described class. You can always use AnimalMailer.daily_message as well, but among other things described_class ensures that if you shuffle or share examples that you are always testing what you think you are.

    Also note that in the case of unit testing a mailer, you're mostly focused on the correct generation of the content. Testing of successful delivery or use in jobs, controllers, etc., would be done as part of request or feature tests.