使用rspec使用should_receive测试ActionMailer

时间:2012-06-05 02:46:54

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

我有一个像这样的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

2 个答案:

答案 0 :(得分:2)

我认为您希望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

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

答案 1 :(得分:2)

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

无论如何,当您在Mailer上调用notification_to_sender方法时,您将获得一个Mail::Message的实例,其中包含deliver方法。如果您只是在不调用Mailer.notification_to_sender的情况下执行deliver,那么您可以使用评论运行您拥有的内容,一切都会好的。我猜你也会打电话给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方法。