【问题标题】:Writing a spec for an observer that triggers a mailer为触发邮件程序的观察者编写规范
【发布时间】:2011-02-16 19:05:57
【问题描述】:

我正在编写一个简单的评论观察器,它会在创建新评论时触发邮件程序。所有相关代码都在这个要点中:https://gist.github.com/c3234352b3c4776ce132

请注意,Notification 的规范通过,但 CommentObserver 的规范失败,因为 Notification.new_comment 正在返回 nil。我发现我可以通过使用它来获得通过规范:

describe CommentObserver do
  it "sends a notification mail after a new comment is created" do
    Factory(:comment)
    ActionMailer::Base.deliveries.should_not be_empty
  end
end

然而,这并不理想,因为它在观察者的规范中测试邮件程序的行为,而我真正想知道的是它正确地触发了邮件程序。为什么邮件程序在原始版本的规范中返回nil?指定此类功能的最佳方法是什么?我正在使用 Rails 3 和 RSpec 2(还有 Factory Girl,如果这很重要的话)。

【问题讨论】:

    标签: ruby-on-rails rspec observer-pattern actionmailer


    【解决方案1】:

    上下文

    class CommentObserver < ActiveRecord::Observer
      def after_create(comment)
        Notification.new_comment(comment).deliver
      end
    end
    
    # spec
    require 'spec_helper'
    
    describe CommentObserver do
      it "sends a notification mail after a new comment is created" do
        @comment = Factory.build(:comment)
        Notification.should_receive(:new_comment).with(@comment)
        @comment.save
      end
    end
    

    在这种情况下,您要检查通知上是否调用了deliver,所以这就是期望应该去的地方。规范代码的其余部分用于设置期望并触发它。试试这个方法:

    describe CommentObserver do
      it "sends a notification mail after a new comment is created" do
        @comment = Factory.build(:comment)
        notification = mock(Notification)
        notification.should_receive(:deliver)
        Notification.stub(:new_comment).with(@comment).and_return(notification)
        @comment.save
      end
    end
    

    为什么邮件程序在 规范的原始版本?

    我相信这是因为消息期望的行为类似于存根——如果在 .and_return() 中未指定值或通过传入块,should_receive 将返回 nil

    【讨论】:

    • 我现在明白了为什么邮件程序返回 nil - 我没有意识到 should_receive 隐式地将它的接收器变成了一个存根。但是,我不同意我想在这里测试的是消息的传递。 Notification 类的规范中已经涵盖了这一点。我想在这里确认的是,调用了 Notification 的 new_comment 方法,并且您展示的示例似乎与 Notification.new_comment 的实现紧密耦合。
    • 公平地说,这不会测试实际交付,它只指定调用deliver。毕竟这个例子被命名为“发送通知邮件”,而不是“创建通知实例”:) 但是如果你想避免检查deliver,你可以将期望设置为'new_comment, and change the mock to mock(Notification)。 as_null_object, so that it ignores the deliver`消息。
    猜你喜欢
    • 2015-11-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-18
    • 2016-11-01
    相关资源
    最近更新 更多