【问题标题】:Test delayed job mailers in Rails method在 Rails 方法中测试延迟的作业邮件
【发布时间】:2019-05-09 12:42:51
【问题描述】:

我有一个 rails 方法,它允许用户提交评论并向交易对手发送一封电子邮件,使用延迟的作业。

def update_review
  @review.add_review_content(review_params)
  ReviewMailer.delay.review_posted(@review.product_owner, params[:id])
end

我正在尝试为此添加rspec 测试,以检查邮件是否正确交付以及交付给谁。延迟的作业在 test 创建后立即运行,因为我希望其他作业(例如更新产品所有者总体评分的作业)立即完成。

所以电子邮件确实被解雇了,但我该如何为其添加测试?

编辑:添加当前测试

我目前的测试是:

describe 'PUT #update the review' do

  let(:attr) do
    { rating: 3.0, raw_review: 'Some example review here' }
   end

   before(:each) do
     @review = FactoryBot.create :review
     put :update, id: @review.id, review: attr
   end

   it 'creates a job' do
     ActiveJob::Base.queue_adapter = :test
     expect {
       AdminMailer.review_posted(@coach, @review.id).deliver_later
     }.to have_enqueued_job
   end 

   it { should respond_with 200 }

end

这确实测试了邮件程序是否正常工作,但我想测试它是否也可以在方法流中正确触发。

【问题讨论】:

    标签: ruby-on-rails rspec actionmailer ruby-on-rails-4.2


    【解决方案1】:

    听起来您想要确保update_review 方法将作业排入队列以将正确的电子邮件发送给正确的收件人。这里有一个更简单的方法来实现:

    describe 'PUT #update the review' do
      let(:params) { { rating: rating, raw_review: raw_review } }
      let(:rating) { 3.0 }
      let(:raw_review) { 'Some example review here' }
      let(:review) { FactoryBot.create(:review) }
      let(:delayed_review_mailer) { instance_double(ReviewMailer) } 
    
      before do
        # assuming this is how the controller finds the review...
        allow(Review).to receive(:find).and_return(review)
    
        # mock the method chain that enqueues the job to send the email
        allow(ReviewMailer).to receive(:delay).and_return(delayed_review_mailer)
        allow(delayed_review_mailer).to receive(:review_posted)
    
        put :update, id: review.id review: params
      end
    
      it 'adds the review content to the review' do
        review.reload
        expect(review.rating).to eq(rating) 
        expect(review.raw_review).to eq(raw_review)
      end
    
      it 'sends a delayed email' do
        expect(ReviewMailer).to have_received(:delay)
      end
    
      it 'sends a review posted email to the product owner' do
        expect(delayed_review_mailer)
          .to have_received(:review_posted)
          .with(review.product_owner, review.id)
      end
    end
    

    我更喜欢这种方法的原因是 a) 它可以在完全不接触数据库的情况下完成(通过将工厂交换为实例 double),并且 b) 它不会尝试测试 Rails 中已经存在的部分由构建 Rails 的人测试过,比如 ActiveJob 和 ActionMailer。你可以相信 Rails 自己对这些类的单元测试。

    【讨论】:

      猜你喜欢
      • 2011-09-15
      • 1970-01-01
      • 2011-06-01
      • 2014-12-22
      • 1970-01-01
      • 2012-04-20
      • 1970-01-01
      • 2015-03-11
      • 2013-11-26
      相关资源
      最近更新 更多