使用参数测试邮件程序的最佳方法

Best way to test a mailer with arguments

我有一个邮件程序传递这样的参数:

AnimalMailer.daily_message(owner).deliver_later

该方法如下所示:

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

我是编写规范的新手,想知道我应该如何将所有者传递给方法并对其进行测试。我目前有这个设置:

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

规范通常遵循三步流程 1) 设置,2) 调用,3) 期待。这适用于像其他任何东西一样的单元测试邮件程序。测试中的调用和参数与一般用途相同,因此在您的情况下:

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

请注意,由于 describe 是正在测试的 class 名称,您可以从那里使用 described_class 来引用所描述的 class。您也可以始终使用 AnimalMailer.daily_message,但除其他事项外,described_class 可确保您在随机播放或分享示例时始终在测试自己的想法。

另请注意,在对邮件程序进行单元测试时,您主要关注内容的正确生成。在作业、控制器等中成功交付或使用的测试将作为请求或功能测试的一部分完成。

在测试之前,确保 config / environment / test.rb 文件设置为:

  config.action_mailer.delivery_method = :test

这确保电子邮件不会实际发送,而是存储在 ActionMailer :: Base.deliveries 数组中。

正在关注 Four-Phase Test

animal_mailer.rb

class AnimalMailer < ApplicationMailer
  default from: 'noreply@animal_mailer.com'

  def daily_message(owner)
    @name = owner.name

    mail(
      to: owner.email,
      subject: "test",
      content_type: "text/html",
      date: Time.now.in_time_zone("Mountain Time (US & Canada)")
    )
  end
end

animal_mailer_spec.rb

RSpec.describe AnimalMailer, type: :mailer do
  describe 'instructions' do
    let(:user) { create(:user, :admin) }
    let(:mail) { described_class.daily_message(user).deliver_now }

    it 'renders the subject' do
      expect(mail.subject).to eq("test")
    end

    it 'renders the receiver email' do
      expect(mail.to).to eq([user.email])
    end

    it 'renders the sender email' do
      expect(mail.from).to eq(['noreply@animal_mailer.com'])
    end

    it 'assigns @name' do
      expect(mail.body.encoded).to match(user.name)
    end
  end
end

如果您有模范用户:

class User
  def send_instructions
    AnimalMailer.instructions(self).deliver_now
  end
end


RSpec.describe User, type: :model do
  subject { create :user }

  it 'sends an email' do
    expect { subject.send_instructions }
      .to change { ActionMailer::Base.deliveries.count }.by(1)
  end
end