ruby-on-rails - for - smtp gmail rails 5
Rails: cómo se prueba que ActionMailer envíe un correo electrónico específico en las pruebas (6)
Actualmente en mis pruebas hago algo como esto para comprobar si un correo electrónico está en cola para ser enviado
assert_difference(''ActionMailer::Base.deliveries.size'', 1) do
get :create_from_spreedly, {:user_id => @logged_in_user.id}
end
pero si una acción del controlador puede enviar dos correos electrónicos diferentes, es decir, uno para el usuario si el registro va bien o una notificación al administrador si algo salió mal, ¿cómo puedo probar cuál fue realmente enviado? El código anterior pasaría independientemente.
A partir de los rieles 3 ActionMailer :: Base.deliveryies es una matriz de Mail :: Message. De la documentación del correo:
# 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@...
De eso debería ser fácil probar tus correos en una integración
mail = ActionMailer::Base.deliveries.last
assert_equal ''[email protected]'', mail[''from''].to_s
assert_equal ''[email protected]'', mail[''to''].to_s
Al utilizar el ActionMailer durante las pruebas, todos los correos se colocan en una gran variedad llamada deliveries
. Lo que básicamente estás haciendo (y es suficiente principalmente) es verificar si hay correos electrónicos en la matriz. Pero si desea verificar específicamente un determinado correo electrónico, debe saber qué se almacena realmente en el conjunto. Afortunadamente, los correos electrónicos se almacenan, por lo que puede recorrer el conjunto y verificar cada correo electrónico.
Consulte ActionMailer :: Base para ver qué métodos de configuración están disponibles, que puede usar para determinar qué correos electrónicos están presentes en la matriz. Algunos de los métodos más adecuados para su caso probablemente sean
-
recipients
: toma una o más direcciones de correo electrónico. Estas direcciones son donde su correo electrónico será entregado. Establece el encabezado A: -
subject
: el asunto de su correo electrónico. Establece el encabezado Asunto:
El marco de prueba debe tener un excelente ayudante que le permita afirmar ciertas condiciones sobre un correo electrónico que se envió. Sí, podría hacerlo usted mismo con ActionMailer.delivery, pero debería hacer que todo sea un pequeño y ordenado bloque
Esta es la mejor manera que he encontrado para hacerlo.
1) Incluye el complemento de devolución de llamada de acción de correo como este:
script/plugin install git://github.com/AnthonyCaliendo/action_mailer_callbacks.git
En realidad, no uso las funciones principales del complemento, pero proporciona la buena funcionalidad de poder averiguar qué método se utilizó para enviar un correo electrónico.
2) Ahora puedes poner algunos métodos en tu test_helper.rb así:
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) Ahora puedes escribir pruebas dulces como esta:
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
Aquí "broadcast" y "mailing_failed" son los nombres de los métodos en mi clase ActionMailer :: Base. Estos son los que normalmente usa al llamar a Mailer.deliver_broadcast(some_data)
o Mailer.deliver_failed_mailing(some_data)
etc. ¡Eso es todo!
Un poco tarde, pero puede ayudar a otros:
Puede usar Email-spec , una colección de Rspec / Minitest matchers y Cucumber steps.
Usando la sintaxis actual de Rspec, terminé usando lo siguiente:
last_email = ActionMailer::Base.deliveries.last
expect(last_email.to).to eq [''[email protected]'']
expect(last_email.subject).to have_content ''Welcome''
El contexto de mi prueba era una especificación de características en la que quería asegurarme de que se enviara un correo electrónico de bienvenida a un usuario después de iniciar sesión.