【问题标题】:How to test with RSpec if an email is delivered如果电子邮件已送达,如何使用 RSpec 进行测试
【发布时间】:2011-09-02 13:50:55
【问题描述】:

如果我使用 :post 调用控制器方法,我想测试是否发送了电子邮件。我将使用 email_spec 所以我在这里剪了这个:http://rubydoc.info/gems/email_spec/1.2.1/file/README.rdoc#Testing_In_Isolation

但这不起作用,因为我将模型对象的一个​​实例传递给交付方法,并且该实例在交付之前被保存。

我尝试创建模型对象的另一个实例,但 id 不一样。

我的控制器方法如下所示:

def create

   @params = params[:reservation]

   @reservation = Reservation.new(@params)
   if @reservation.save
      ReservationMailer.confirm_email(@reservation).deliver
      redirect_to success_path
   else
      @title = "Reservation"
      render 'new'
   end

end

你有什么办法解决这个问题吗?

【问题讨论】:

    标签: ruby-on-rails-3 rspec2


    【解决方案1】:

    假设您的测试环境以通常的方式设置(即,您有config.action_mailer.delivery_method = :test),然后发送的电子邮件将作为Mail::Message 实例插入到全局数组ActionMailer::Base.deliveries 中。您可以从测试用例中读取它并确保电子邮件符合预期。见here

    【讨论】:

    • 谢谢。我花了一些时间来理解它,但现在我收到了email = ActionMailer::Base.deliveries.last 的最后一封邮件,之后我可以使用emailEmail Spec 的测试。
    • ActionMailer::Base.deliveries 对我来说总是空的。我有一个没有配置 ActiveJob 或 ActionMailer 的 Rails 6 项目。按照 ActionMailer 指南设置示例,然后在这里结束。我正在使用enqueued_jobs,而不是按照此处的建议:stackoverflow.com/a/41180453/2771889
    【解决方案2】:

    配置您的测试环境以在ActionMailer::Base.deliveries 中累积发送的邮件。

    # config/environments/test.rb
    config.action_mailer.delivery_method = :test
    

    那么这样的事情应该可以让您测试邮件是否已发送。

    # Sample parameters you would expect for POST #create.
    def reservation_params
      { "reservation" => "Drinks for two at 8pm" }
    end
    
    describe MyController do
      describe "#create" do
        context "when a reservation is saved" do
          it "sends a confirmation email" do
            expect { post :create, reservation_params }.to change { ActionMailer::Base.deliveries.count }.by(1)
          end
        end
      end
    end
    

    请注意,我的示例使用 RSpec 3 语法。

    【讨论】:

      【解决方案3】:

      我知道我参加这个聚会迟到了,但对于未来的 Google 员工...

      我认为这个问题的更好的解决方案是回答here

      之前接受的答案是测试 Mailer 本身(在控制器规范中)。您应该在这里测试的是,Mailer 被告知使用正确的参数传递一些东西。

      然后您可以在其他地方测试 Mailer 以确保它正确响应这些参数。

      ReservationMailer.should_receive(:confirm_email).with(an_instance_of(Reservation))

      【讨论】:

      • 您可能想要检查,例如,当控制器或模型中发生某些事情时没有发送电子邮件。在这种情况下,您仍然必须使用 ActionMailer::Base.deliveries。这不是不同意,只是作为这个答案的补充。
      • 这似乎是一个流行的答案,所以我想我补充说ReservationMailer.confirm_email 返回一个MailMessage,它不发送电子邮件。您还需要检查在上述MailMessage 上是否调用了deliver 方法。对于更优雅的解决方案,您可能需要使用像 EventBus 这样的 Gem,这样您就可以分离您的顾虑。 EventBus 将让您宣布“reservation.created”并有一个单独的侦听器,然后在适当的情况下异步发送电子邮件(推荐)。
      【解决方案4】:

      任何使用 rspec +3.4 和 ActiveJob 发送异步电子邮件的人,请尝试:

      expect {
        post :create, params
      }.to have_enqueued_job.on_queue('mailers')
      

      【讨论】:

        【解决方案5】:

        这是测试使用正确参数调用 Mailer 的方法。您可以在功能、控制器或邮件规范中使用此代码:

        delivery = double
        expect(delivery).to receive(:deliver_now).with(no_args)
        
        expect(ReservationMailer).to receive(:confirm_email)
          .with('reservation')
          .and_return(delivery)
        

        【讨论】:

        【解决方案6】:

        要添加更多内容,请确保如果您要使用 should_receive 存根调用,您在其他地方进行了集成测试,测试您实际上是否正确调用了该方法。

        我已经有几次通过更改在其他地方使用 should_receive 测试的方法并且在方法调用被中断时仍然通过测试。

        如果您更喜欢测试结果而不是使用 should_receive,should 有一个很好的匹配器,其工作方式如下:

        it { should have_sent_email.with_subject(/is spam$/) }
        

        Shoulda documentation

        More information on using Shoulda Matchers with rSpec

        【讨论】:

        【解决方案7】:

        如果您将 CapybaraCapybara Email 一起使用,并且您向 test@example.com 发送了电子邮件,您也可以使用此方法:

        email = open_email('test@example.com')
        

        然后你可以像这样测试它:

        expect(email.subject).to eq('SUBJECT')
        expect(email.to).to eq(['test@example.com'])
        

        【讨论】:

          【解决方案8】:

          试试email-spec

          describe "POST /signup (#signup)" do
            it "should deliver the signup email" do
              # expect
              expect(UserMailer).to(receive(:deliver_signup).with("email@example.com", "Jimmy Bean"))
              # when
              post :signup, "Email" => "email@example.com", "Name" => "Jimmy Bean"
            end
          end
          

          更多示例:https://github.com/email-spec/email-spec#testing-in-isolation

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 2012-01-24
            • 2011-07-12
            • 2020-08-07
            • 1970-01-01
            • 1970-01-01
            • 2017-02-01
            • 1970-01-01
            相关资源
            最近更新 更多