Rails – 你如何testingActionMailer在testing中发送了一个特定的电子邮件

目前在我的testing中,我做了这样的事情来testing电子邮件是否排队发送

assert_difference('ActionMailer::Base.deliveries.size', 1) do get :create_from_spreedly, {:user_id => @logged_in_user.id} end 

但如果ia控制器的行动可以发送两个不同的电子邮件,即一个用户如果注册罚款或通知pipe理员,如果出了问题 – 我怎么能testing哪一个实际得到发送。 上面的代码会通过。

在testing过程中使用ActionMailer时,所有的邮件都放在一个大数组中,称为deliveries 。 你基本上正在做什么(主要是足够的)是检查数组中是否存在电子邮件。 但是,如果你想专门检查某个电子邮件,你必须知道实际存储在数组中的内容。 幸运的是,电子邮件本身是存储的,因此您可以遍历数组并检查每封电子邮件。

请参阅ActionMailer :: Base以查看可用的configuration方法,您可以使用它来确定数组中存在哪些电子邮件。 一些最适合你的情况的方法可能是

  • recipients :收取一个或多个电子邮件地址。 这些地址是您的电子邮件将被传送到的地方。 设置To:标题。
  • subject :您的电子邮件的主题。 设置主题:标题。

至于rails 3,ActionMailer :: Base.deliveries是一个Mail :: Message的数组。 从邮件文档:

 # mail['from'] = 'mikel@test.lindsaar.net' # mail[:to] = 'you@test.lindsaar.net' # mail.subject 'This is a test email' # mail.body = 'This is a body' # # mail.to_s #=> "From: mikel@test.lindsaar.net\r\nTo: you@... 

从这应该很容易testing你的邮件在一个集成

 mail = ActionMailer::Base.deliveries.last assert_equal 'mikel@test.lindsaar.net', mail['from'].to_s assert_equal 'you@test.lindsaar.net', mail['to'].to_s 

使用当前的Rspec语法,我结束了使用以下内容:

 last_email = ActionMailer::Base.deliveries.last expect(last_email.to).to eq ['test@example.com'] expect(last_email.subject).to have_content 'Welcome' 

我的testing环境是一个function规范,我想确保在注册后向用户发送欢迎邮件。

testing框架shoulda有一个优秀的帮手,让你断言发送的电子邮件的某些条件。 是的,你可以用ActionMailer.deliveries自己做,但是应该把它做成一个整齐的小块

这是我发现的最好的方法。

1)包括这样的动作邮件程序callback插件:

 script/plugin install git://github.com/AnthonyCaliendo/action_mailer_callbacks.git 

我并没有真正使用插件的主要function,但它提供了能够找出哪种方法用于发送电子邮件的好function。

2)现在你可以在你的test_helper.rb中添加一些方法:

  def assert_sent(method_name) assert sent_num_times(method_name) > 0 end def assert_not_sent(method_name) assert sent_num_times(method_name) == 0 end def assert_sent_once(method_name) assert sent_num_times(method_name) == 1 end def sent_num_times(method_name) count = 0 @emails.each do |email| count += 1 if method_name == email.instance_variable_get("@method_name") end count end 

3)现在你可以写这样的甜蜜testing:

 require 'test_helper' class MailingTest < ActionController::IntegrationTest def setup @emails = ActionMailer::Base.deliveries @emails.clear end test "should send a mailing" do assert_difference "Mailing.count", 1 do feeds(:feed1).generate_mailing end assert_sent_once "broadcast" assert_not_sent "failed_mailing" end end 

这里“broadcast”和“mailing_failed”是我的ActionMailer :: Base类中的方法名称。 这些是你通常使用通过调用Mailer.deliver_broadcast(some_data)Mailer.deliver_failed_mailing(some_data)等。就是这样!

有点晚了,但可能会帮助别人:

您可以使用电子邮件规范 ,Rspec / Minitest匹配器和黄瓜步骤的集合。