在 RSpec 测试后清除 ActionMailer::Base.deliveries

Posted

技术标签:

【中文标题】在 RSpec 测试后清除 ActionMailer::Base.deliveries【英文标题】:Clearing out ActionMailer::Base.deliveries after RSpec test 【发布时间】:2011-08-16 03:25:56 【问题描述】:

我的 UserMailer 类有以下 RSpec 测试:

require "spec_helper"

describe UserMailer do
  it "should send welcome emails" do
    ActionMailer::Base.deliveries.should be_empty
    user = Factory(:user)
    UserMailer.welcome_email(user).deliver
    ActionMailer::Base.deliveries.should_not be_empty
  end
end

此测试第一次通过,但第二次运行失败。在进行了一些调试之后,似乎第一个测试向 ActionMailer::Base.deliveries 数组添加了一个项目,并且该项目从未被清除。这会导致测试中的第一行失败,因为数组不是空的。

在 RSpec 测试之后清除 ActionMailer::Base.deliveries 数组的最佳方法是什么?

【问题讨论】:

为什么不应该在您的setup 块中使用ActionMailer::Base.deliveries = [] 此规范是否位于spec/mailers/ 【参考方案1】:
RSpec.describe UserMailer do
  before do
    # ActionMailer::Base.deliveries is a regular array
    ActionMailer::Base.deliveries = []

    # or use ActionMailer::Base.deliveries.clear
  end

  it "sends welcome email" do
    user = create(:user)
    UserMailer.welcome_email(user).deliver_now
    expect(ActionMailer::Base.deliveries).to be_present
  end
end

【讨论】:

为了避免重复,你可以把它放在spec_helper.rb的config块中:config.before(:each) ActionMailer::Base.deliveries.clear 这不是必需的,因为应该设置 RSpec 邮件规范以自动清除交付数组。详情请见github.com/rspec/rspec-rails/issues/661。 它应该适用于邮件规范,但不适用于请求规范 - 然后你需要以某种方式自己清除它。我?我要使用 Luke Francl 方法。【参考方案2】:

正如安迪·林德曼(Andy Lindeman)所指出的,对于邮件测试,清理交付是自动完成的。但是,对于其他类型,只需将 , :type => :mailer 添加到包装块即可强制执行相同的行为。

describe "tests that send emails", type: :mailer do
  # some tests
end

【讨论】:

感谢您的提示!这对我来说感觉像是一种更清洁的方法。适用于 Rails 4.1 和 Rspec 3.1。 是的。这是我遇到的问题。我忘了加type: :mailer。谢谢 d_rail! 这对我来说似乎很脆弱。用特殊标志装饰测试用例,使它们以不明显的方式运行。我更喜欢其他答案。 将“mailer”标签添加到并非专门为 mailer 单元测试的测试似乎已损坏。我宁愿选择其他方法之一。【参考方案3】:

您可以在每次测试后轻松清除交付,将其添加到您的 spec_helper.rb 中。

RSpec.configure do |config|
  config.before  ActionMailer::Base.deliveries.clear       
end

我建议阅读我关于 correct emails configuration in Rails 的文章,其中我还谈到了正确测试它们。

【讨论】:

这似乎是迄今为止最清晰的解决方案。对于使用 email-spec 的项目,请考虑在 before 块中调用 reset_mailer 来代替 ActionMailer::Base.deliveries.clear,因为 reset_mailer 会做一些额外的工作,这可能会有所帮助。 RSpec.configure do |config| config.before(:each) reset_mailer end

以上是关于在 RSpec 测试后清除 ActionMailer::Base.deliveries的主要内容,如果未能解决你的问题,请参考以下文章

资产预编译后,RSpec / Capybara测试不会通过

RSpec:如何测试一个方法是不是被调用?

Rspec功能测试:无法访问路径

rspec 示例后解冻时间

RSpec 中的夹具

Rspec 不显示邮件正文中的内容