使用rails 3中的ActionMailer以测试模式发送电子邮件

时间:2010-12-07 15:09:41

标签: ruby-on-rails ruby-on-rails-3 actionmailer

在使用Rails 3

的测试模式下发送邮件时,我遇到了一个奇怪的问题

似乎我的邮寄者没有退回任何东西。例如,我有一个名为UserMailer的邮件程序。用户可以在应用程序中进行需要批准的更改,这样就会有一个名为changes_approved的方法,该方法应该向用户发送一封电子邮件,通知他们他们的更改已被批准..class

UserMailer < ActionMailer::Base

  default :from => "from@example.com"

  def changes_approved(user, page)

    @user = user
    @page = page

    mail(:to => user.email, :subject => "Your changes have been approved")

  end

end

在我的控制器中,我有以下一行

UserMailer.changes_approved(@page_revision.created_by, @page_revision.page).deliver

然而,此时我的测试失败并出现错误:

未定义的方法`deliver'代表nil:NilClass

当我在开发网站上触发相同的操作(http:// localhost:3000通过浏览器)时,电子邮件会被正确发送出去,一切都很愉快

为了进一步增加混淆,我正在使用设计进行身份验证,而且电子邮件似乎在测试和开发模式下都能正常工作。当然,我没有得到同样的错误,根据我的电子邮件规范测试,每个人都在工作

所以这让我相信我的邮件有问题,而不是我的测试邮件配置本身,但我不知道是什么。任何建议将不胜感激

由于

4 个答案:

答案 0 :(得分:10)

我使用了https://gist.github.com/1031144 转换

# Rails 2 method:
UserMailer.should_receive(:deliver_signup)

# Cumbersome Rails 3 method:
mailer = mock
mailer.should_receive(:deliver)
UserMailer.should_receive(:signup).and_return(mailer)

答案 1 :(得分:5)

我遇到了类似的问题 - 可能是UserMailer.changes_approved方法被替换为模拟方法,该方法返回nil(我没有使用shoulda进行该测试,但这是我最好的猜测)。

我的代码看起来像这样(修改为使用您的示例):

UserMailer.expects(:changes_approved).once

我用额外的存根修复了它:

@mailer = stub(:deliver)
UserMailer.expects(:changes_approved).once.returns(@mailer)

nil现在被@mailer取代。

答案 2 :(得分:2)

要测试延迟的动作邮件程序,我们需要先将delayed_job的配置(在config / initializers / delayed_job_config.rb中)更改为

Delayed::Worker.delay_jobs = !Rails.env.test?

并且在您的测试中,期望值应设置为

mock_mail = mock(:mail)
mock_mail.should_receive(:deliver)
UserMailer.should_receive(:changes_approved).with(user, page).and_return(mock_mail)

答案 3 :(得分:1)

我找到了答案,

看起来问题出在我测试这些邮件的方式上。在每个控制器测试中,我都有类似于

的行
UserMailer.should_receive(:changes_approved).with(user, page)

虽然这个测试通过很好,但似乎打破了邮件本身。我从测试中删除了这一行,现在他们通过了确定。对ActionMailer :: Base.deliveries.last的后续测试检查发送的电子邮件的详细信息是正确的,所以我很高兴这条线不是必需的。

如果有人解释为什么会破坏这个,我会有兴趣找出

非常感谢