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

Kev*_*ang 58 unit-testing rspec ruby-on-rails actionmailer

我的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
Run Code Online (Sandbox Code Playgroud)

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

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

Pet*_*own 84

由于AM :: Base.deliveries只是一个数组,因此可以将其初始化为空数组.你可以摆脱第一次检查,它也是空的:

describe UserMailer do
  before { ActionMailer::Base.deliveries = [] }

  it "should send welcome emails" do
    user = Factory(:user)
    UserMailer.welcome_email(user).deliver
    ActionMailer::Base.deliveries.should_not be_empty
  end
end
Run Code Online (Sandbox Code Playgroud)

  • 为了避免重复这一点,你可以把它放在spec_helper.rb的配置块中:`config.before(:each){ActionMailer :: Base.deliveries.clear}` (62认同)
  • 这不应该是必需的,因为应该设置RSpec邮件程序规范以自动清除交付数组.有关详细信息,请参阅https://github.com/rspec/rspec-rails/issues/661. (8认同)
  • 它应该适用于邮件程序规范,但不适用于请求规范 - 那么你需要以某种方式自己清除它.我?我要去Luke Francl方法. (2认同)

coo*_*sse 50

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

RSpec.configure do |config|
  config.before { ActionMailer::Base.deliveries.clear }      
end
Run Code Online (Sandbox Code Playgroud)

我建议阅读我关于Rails正确的电子邮件配置的文章,我还会谈到正确测试它们.

  • 到目前为止,这似乎是最清晰的解决方案.对于使用[email-spec](https://github.com/bmabey/email-spec)的项目,考虑在before块中调用`reset_mailer`代替`ActionMailer :: Base.deliveries.clear`作为`reset_mailer`做一些可能有用的额外工作.`RSpec.configure do | config | config.before(:each){reset_mailer} end` (6认同)

d_r*_*ail 10

正如Andy Lindeman指出的那样,清除交付是自动完成的邮件测试.但是,对于其他类型,只需添加, :type => :mailer到包装块以强制执行相同的操作.

describe "tests that send emails", type: :mailer do
  # some tests
end
Run Code Online (Sandbox Code Playgroud)