Ruby-on-rails Rails - 你如何测试 ActionMailer 在测试中发送了特定的电子邮件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2063438/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Rails - How do you test ActionMailer sent a specific email in tests
提问by robodisco
Currently in my tests I do something like this to test if an email is queued to be sent
目前在我的测试中,我做这样的事情来测试电子邮件是否排队等待发送
assert_difference('ActionMailer::Base.deliveries.size', 1) do
get :create_from_spreedly, {:user_id => @logged_in_user.id}
end
but if i a controller action can send two different emails i.e. one to the user if sign up goes fine or a notification to admin if something went wrong - how can i test which one actually got sent. The code above would pass regardless.
但是,如果 ia 控制器操作可以发送两封不同的电子邮件,即如果注册正常则向用户发送一封电子邮件,或者如果出现问题则向管理员发送通知 - 我如何测试实际发送的是哪一封。无论如何,上面的代码都会通过。
采纳答案by Veger
When using the ActionMailer during tests, all mails are put in a big array called deliveries. What you basically are doing (and is sufficient mostly) is checking if emails are present in the array.
But if you want to specifically check for a certain email, you have to know what is actually stored in the array. Luckily the emails themselves are stored, thus you are able to iterate through the array and check each email.
在测试期间使用 ActionMailer 时,所有邮件都放在一个名为deliveries. 您基本上正在做的(并且主要是足够的)是检查数组中是否存在电子邮件。但是如果要专门检查某封电子邮件,则必须知道数组中实际存储的是什么。幸运的是,电子邮件本身已被存储,因此您可以遍历数组并检查每封电子邮件。
See ActionMailer::Baseto see what configuration methods are available, which you can use to determine what emails are present in the array. Some of the most suitable methods for your case probably are
请参阅ActionMailer::Base以查看可用的配置方法,您可以使用这些方法来确定数组中存在哪些电子邮件。一些最适合您的情况的方法可能是
recipients: Takes one or more email addresses. These addresses are where your email will be delivered to. Sets the To: header.subject: The subject of your email. Sets the Subject: header.
recipients:需要一个或多个电子邮件地址。这些地址是您的电子邮件将被发送到的地方。设置 To: 标题。subject: 邮件主题。设置主题:标题。
回答by todd
As of rails 3 ActionMailer::Base.deliveries is an array of Mail::Message's. From the mail documentation:
从 Rails 3 开始,ActionMailer::Base.deliveries 是 Mail::Message 的数组。从邮件文档:
# mail['from'] = '[email protected]'
# mail[:to] = '[email protected]'
# mail.subject 'This is a test email'
# mail.body = 'This is a body'
#
# mail.to_s #=> "From: [email protected]\r\nTo: you@...
From that it should be easy to test your mail's in an integration
因此,在集成中测试您的邮件应该很容易
mail = ActionMailer::Base.deliveries.last
assert_equal '[email protected]', mail['from'].to_s
assert_equal '[email protected]', mail['to'].to_s
回答by Neal
Using current Rspec syntax, I ended up using the following:
使用当前的 Rspec 语法,我最终使用了以下内容:
last_email = ActionMailer::Base.deliveries.last
expect(last_email.to).to eq ['[email protected]']
expect(last_email.subject).to have_content 'Welcome'
The context of my test was a feature spec where I wanted to make sure a welcome email was sent to a user after signing up.
我的测试上下文是一个功能规范,我想确保在注册后向用户发送欢迎电子邮件。
回答by RyanWilcox
The test framework shouldahas an excellent helper which lets you assert certain conditions about an email that was sent. Yes, you could do it yourself with ActionMailer.deliveries, but shoulda makes it all one neat little block
测试框架应该有一个出色的助手,它可以让您断言有关已发送电子邮件的某些条件。是的,你可以用 ActionMailer.deliveries 自己做,但应该把这一切变成一个整洁的小块
回答by guapolo
A little late, but it may help others:
有点晚了,但它可能会帮助其他人:
You could use Email-spec, a collection of Rspec/Minitest matchers and Cucumber steps.
您可以使用Email-spec,一组 Rspec/Minitest 匹配器和 Cucumber 步骤。
回答by Brian Armstrong
Here is the best way I've found to do it.
这是我找到的最好的方法。
1) Include the action mailer callbacksplugin like this:
1)包括这样的动作邮件回调插件:
script/plugin install git://github.com/AnthonyCaliendo/action_mailer_callbacks.git
I don't really use the plugin's main features, but it does provide the nice functionality of being able to figure out which method was used to send an email.
我并没有真正使用该插件的主要功能,但它确实提供了很好的功能,能够确定使用哪种方法发送电子邮件。
2) Now you can put some methods in your test_helper.rb like this:
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) Now you can write sweet tests like this:
3)现在你可以像这样编写甜蜜的测试:
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
Here "broadcast" and "mailing_failed" are the names of the methods in my ActionMailer::Base class. These are the ones you normally use by calling Mailer.deliver_broadcast(some_data)or Mailer.deliver_failed_mailing(some_data)etc. That's it!
这里的“broadcast”和“mailing_failed”是我的 ActionMailer::Base 类中方法的名称。这些都是你通常通过调用使用的那些Mailer.deliver_broadcast(some_data)或Mailer.deliver_failed_mailing(some_data)等等。这就是它!

