在rspec测试时,ActionMailer方法调用在模块中返回nil

dna*_*oli 9 rspec ruby-on-rails actionmailer ruby-on-rails-3

ActionMailer上课了

class UserMailer < ActionMailer::Base 
  default from: "no-reply@spicy-millennium.com" 

  def submission_reminder user 
    @user = user           
    mail :to => user.email, :subject => "Your timesheet needs to be submitted!" 
  end    
end
Run Code Online (Sandbox Code Playgroud)

如果我UserMailer.submission_reminder(current_user)在开发中调用它会返回一个Mail::Message像预期的对象.

我的应用程序中调用此方法的位置在lib文件夹中的模块中:

module TimesheetSubmissionNotifier                            
  def self.send_submission_reminders
    User.all.each { |user| UserMailer.submission_reminder(user).deliver }
  end
end
Run Code Online (Sandbox Code Playgroud)

当我TimesheetSubmissionNotifier.send_submission_reminders在开发中调用时,UserMailer.submission_remind(user)返回邮件消息并调用deliver,一切正常.

问题是当我TimesheetSubmissionNotifier.send_submission_reminders通过rspec测试调用时,UserMailer.submission_reminder(user)返回nil.

如果我UserMailer.submission_reminder(user)直接从rspec测试中调用,它将返回预期的邮件消息.

以下是我的config/environment/test.rb中与ActionMailer相关的唯一行:

config.action_mailer.delivery_method = :test 
config.action_mailer.default_url_options = { :host => 'localhost:3000' }
Run Code Online (Sandbox Code Playgroud)

任何想法为什么该方法返回零?

dna*_*oli 16

对于那些有类似问题的人,我发现了这个问题.

我正在使用should_receiveRSpec期望,我没有意识到实际上创建了它所放置的类的模拟.所以我完全嘲笑UserMailer类,这意味着它永远不会到达实际的UserMailer类.

我无法通过使用模拟函数来实现它,所以我改变了测试以查看UserMailer.deliveries商店并检查是否有适量的消息放在那里并且它们被发送到正确的电子邮件地址.

  • 我们遇到了这个升级到rails 4的问题.我们使用的是sidekiq延迟,它在升级过程中发生了变化,如果邮件程序返回nil,则会引发RuntimeError'返回无法传递的邮件对象'.Mailer.should_receive(:submission_reminder).and_call_original修复了测试. (3认同)
  • 从技术上讲,should_receive 不会创建模拟对象,它会删除该方法并返回 nil (rspec 文档将此称为部分模拟)。您可以使用 and_call_original 调用原始方法。例如。should_receive(:submission_reminder).and_call_original (2认同)