【问题标题】:Using rspec to test ActionMailer with should_receive使用 rspec 通过 should_receive 测试 ActionMailer
【发布时间】:2012-06-09 02:16:16
【问题描述】:

我有一个这样的 RSpec 测试:

it "should ..." do
  # mailer = mock
  # mailer.should_receive(:deliver)
  Mailer.should_receive(:notification_to_sender)#.and_return(mailer)

  visit transactions_path
  expect do
    page.should_not have_css("table#transactions_list tbody tr")
    find('#some_button').click
    page.should have_css("table#transactions_list tbody tr", :count => 1)
  end.to change{Transaction.count}.by(1)
end

如果我删除顶部的注释部分,则测试通过。但是随着注释部分的到位(我希望如何编写它),测试失败了。

我从网上的一些谷歌搜索中得到了评论部分,但我真的不明白它在做什么或为什么会修复它。似乎应该有一种更清洁的方法来测试没有这个的电子邮件。

谁能解释一下?谢谢!

我正在使用 rails 3 和 rspec-rails 2.10.1

【问题讨论】:

    标签: ruby-on-rails rspec rspec2 rspec-rails


    【解决方案1】:

    我认为您希望 Mailer 的实例接收 notification_to_sender 而不是类。来自 Rails API

    您永远不会实例化您的邮件程序类。相反,您的交付实例方法会自动包装在以单词 Deliver_ 开头的类方法中,后跟您要交付的邮件方法的名称。上面定义的 signup_notification 方法是通过调用 Notifier.deliver_signup_notification 来传递的。

    所以我会使用

    Mailer.any_instance.should_receive(:notification_to_sender)
    

    另外,如果您需要获取最后发送的消息,请使用

    ActionMailer::Base.deliveries.last
    

    我认为这应该可以解决您的问题。

    【讨论】:

    • 嗯,我不知道为什么,但它似乎仍然失败:/ 显示的错误似乎没有意义(来自不同的行)但是当我评论 should_receive 行时它再次起作用。哦,好吧..目前正在处理更大的问题。
    • ActionMailer API 实际上从 Rails 2.x 中的 Mailer.deliver_notification_to_sender 更改为 Rails 3.0 中的 Mailer.notification_to_sender.deliver。鉴于这种变化,交付实例方法不再包含在类方法中,因为如果没有交付调用,您将返回一个 Mail::Message 的实例
    【解决方案2】:

    您可能会在控制器中调用Mailer.notification_to_sender.deliver,或者更好的是,调用后台作业。我猜 notification_to_sender 可能也需要一个参数。

    无论如何,当您在 Mailer 上调用 notification_to_sender 方法时,您将返回一个带有 deliver 方法的 Mail::Message 实例。如果您只是在执行Mailer.notification_to_sender 而不调用deliver,您可以使用 cmets 运行您所拥有的一切,一切都会好起来的。不过我猜你也会打电话给deliver

    在这种情况下,您的失败消息将类似于

    NoMethodError:
      undefined method `deliver' for nil:NilClass
    

    这是因为nil 在很多时候是 Ruby 的默认返回值,Rails 也继承了它。如果不指定 mailer = mock.and_return(mailer) 部分,当控制器在测试上下文中执行时,notification_to_sender 将返回 nil 并且控制器将尝试在该 nil 对象上调用 deliver

    您注释掉的解决方案是模拟出notification_to_sender 的返回值(通常为Mail::Message),然后期望在其上调用deliver 方法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-11-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多