Ruby on rails 使用rspec测试ActionMailer的should\u receive

Ruby on rails 使用rspec测试ActionMailer的should\u receive,ruby-on-rails,rspec,rspec2,rspec-rails,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 tb

我的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,我想您希望Mailer的一个实例接收发送通知,而不是类。来自Rails API

你从来没有实例化过你的邮件类。相反,您的传递实例方法自动包装在类方法中,这些类方法以单词deliver_u开头,后跟您要传递的mailer方法的名称。上面定义的注册通知方法是通过调用Notifier.deliver\u signup\u notification传递的

因此,我会使用

Mailer.any_instance.should_receive(:notification_to_sender)
此外,如果您需要获取上次传递的消息,请使用

ActionMailer::Base.deliveries.last

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

您可能正在呼叫
邮件发送人。通知发送人。在您的控制器中发送
,或者更好的是,在后台工作。我猜通知发送者可能也需要一个参数

无论如何,当您在Mailer上调用
notification\u to\u sender
方法时,您将返回一个
Mail::Message
实例,该实例上有
deliver
方法。如果您只是简单地向发送者发送
Mailer.notification\u
,而不同时调用
deliver
,您可以在那里运行您的评论,一切都会很好。我猜你也在打电话给
deliver

在这种情况下,您的失败消息如下

NoMethodError:
  undefined method `deliver' for nil:NilClass
这是因为
nil
在大多数情况下是Ruby的默认返回值,Rails也继承了该值。在不指定
mailer=mock
以及_return(mailer)
部分的情况下,当控制器在测试上下文中执行时,发送给发送方的通知将返回nil,控制器将尝试调用该nil对象的
deliver


您已经注释掉的解决方案是模拟
通知发送人的返回值(通常是
邮件::消息
),然后期望对其调用
传递
方法。

嗯,我不确定为什么,但似乎仍然失败:/所显示的错误似乎没有意义(从另一行)但是当我评论“应该接收”行时,它又起作用了。哦,好吧,现在转到更大的问题。ActionMailer API实际上已经从Rails 2.x中的
Mailer.deliver\u notification\u to\u sender
更改为Rails 3.0中的
Mailer.notification\u to\u sender.deliver
。考虑到这一变化,传递实例方法不再包装在类方法中,因为没有传递调用,您将返回
Mail::Message