rails for ruby-on-rails unit-testing actionmailer

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.