我的某个测试遇到了问题
Rspec的
it 'should call send_email_notification on NotificationMailer' do
expect(NotificationMailer).to receive(:user_notification).with(an_instance_of(User))
FactoryGirl.create(:user, shop: Shop.new)
end
方法:
def send_email_notification
if user? && self.shop.email_notifications
NotificationMailer.user_notification(self).deliver_now
end
end
未定义的方法`deliver_now'为零:NilClass
这意味着NotificationMailer.user_notification(self)在测试期间返回nil。但是当我在真实的本地环境中运行binding.pry时,NotificationMailer.user_notification(self)会返回正确的对象。这意味着我的测试不起作用......
你会解决什么?
答案 0 :(得分:2)
使用expect.to receive
是 mock - 基本上是一个期望的存根(纯粹主义者可能不同意,但无论如何)。你已经剔除了你所期望的方法,因此它不会被调用。通常,您还会指定返回值,因此您正在测试的其余代码将继续使用该返回值。
您未在此处指定返回值,因此模拟返回nil
,使得其余代码(取决于实际返回值)爆炸。
这里有两种典型的行动方式:
在模拟结束时使用.and_call_original
- 这基本上意味着模拟不会像存根一样,并且会使用您传入的参数调用原始方法。在这种情况下,可能不希望这样,因为它是邮件程序,并且您不想在您的规范中发送电子邮件。
使用.and_return
指定存根的返回值。在这种情况下,您可能需要以下内容:
expect(NotificationMailer)。接收(:user_notification).with(an_instance_of(User))。and_return(double(deliver:true))
当您致电NotificationMailer.user_notification
时,这会向您的代码返回测试双,它会响应deliver
方法并返回true
。
有关测试双打的更多信息,请参阅RSpec Mocks文档: