Pytest-django: ¿`mail.outbox` no está configurado?

Creado en 10 abr. 2018  ·  14Comentarios  ·  Fuente: pytest-dev/pytest-django

¡Hola, gracias por pytest-django! Aprecio todo el trabajo duro, lo he usado varias veces sin problemas.

Nos encontramos con un pequeño inconveniente en el que actualizamos algunas cosas y, de repente, mail.outbox no retiene los correos electrónicos durante las pruebas. Intenté averiguar cómo usar exactamente el accesorio mailoutbox como se documenta aquí, pero tengo problemas para usarlo.

Ahora mismo estamos probando en una clase y he probado bastantes configuraciones para pasar mailoutbox fixture. Es decir, actualicé el ini:

[pytest]
usefixtures = mailoutbox

Sin embargo, no estoy exactamente seguro de cómo usar ese dispositivo, intenté agregar el argumento posicional mailoutbox a mis métodos de clase, pero todavía no puedo acceder a él ... Estoy seguro de que me estoy perdiendo algo simple.

Agradecería un empujón en la dirección correcta y, de nuevo, ¡muchas gracias por este proyecto!

bug

Comentario más útil

Creo que estoy teniendo el mismo problema, así que decidí reducir mi prueba a un envío de correo electrónico básico y ejecutarla individualmente:

def test_reset_password(mailoutbox, db, settings):
    text_message = render_to_string('emails/password_reset/password_reset_successful.txt',
                                    context={})
    html_message = render_to_string('emails/password_reset/password_reset_successful.html',
                                    context={})
    subject = render_to_string('emails/password_reset/password_reset_successful_subject.txt',
                               context={})

    email = EmailMultiAlternatives(
        subject=subject,
        body=text_message,
        from_email="[email protected]",
        to=['[email protected]']
    )

    if html_message:
        email.attach_alternative(html_message, "text/html")
    email.send()

    print(settings.EMAIL_BACKEND)

    assert len(mailoutbox) == 1
>       assert len(mailoutbox) == 1
E       assert 0 == 1
E        +  where 0 = len([])

accounts/tests/api/test_reset_password.py:200: AssertionError
----------------------------------------------- Captured stdout call ------------------------------------------------
django.core.mail.backends.locmem.EmailBackend
--------------------------------------------- Captured stdout teardown ----------------------------------------------

Ahora lo bueno es que si elimino el accesorio db , la prueba pasa. Así que intenté eliminar mi método django_db_setup , pero fue en vano ...

Estoy atascado en este momento.

Todos 14 comentarios

Consulte https://github.com/pytest-dev/pytest-django/blob/5da0935731d71aa347c57cd1753f51e3ba9f32d5/docs/helpers.rst#clearing -of-mailoutbox (7aee367).
(Sin embargo, no está claro si entiendo el problema correctamente)

Creo que estoy teniendo el mismo problema, así que decidí reducir mi prueba a un envío de correo electrónico básico y ejecutarla individualmente:

def test_reset_password(mailoutbox, db, settings):
    text_message = render_to_string('emails/password_reset/password_reset_successful.txt',
                                    context={})
    html_message = render_to_string('emails/password_reset/password_reset_successful.html',
                                    context={})
    subject = render_to_string('emails/password_reset/password_reset_successful_subject.txt',
                               context={})

    email = EmailMultiAlternatives(
        subject=subject,
        body=text_message,
        from_email="[email protected]",
        to=['[email protected]']
    )

    if html_message:
        email.attach_alternative(html_message, "text/html")
    email.send()

    print(settings.EMAIL_BACKEND)

    assert len(mailoutbox) == 1
>       assert len(mailoutbox) == 1
E       assert 0 == 1
E        +  where 0 = len([])

accounts/tests/api/test_reset_password.py:200: AssertionError
----------------------------------------------- Captured stdout call ------------------------------------------------
django.core.mail.backends.locmem.EmailBackend
--------------------------------------------- Captured stdout teardown ----------------------------------------------

Ahora lo bueno es que si elimino el accesorio db , la prueba pasa. Así que intenté eliminar mi método django_db_setup , pero fue en vano ...

Estoy atascado en este momento.

Olvidé mencionar que hay algunas pruebas, en el mismo proyecto, donde el accesorio mailoutbox parece funcionar, así que traté de detectar cualquier diferencia entre esas pruebas y la que falla.
La única diferencia que encontré es el posicionamiento del argumento mailoutbox en la función de prueba. Si está antes de cualquier accesorio que dependa del accesorio db , no funciona, pero funciona si lo coloco después, así que supongo que encontré una solución.

Puedo confirmar que también estamos viendo este comportamiento con pytest-django == 3.3.3

@bogdanpetrea
Gracias por la investigación / actualización.
Será útil para alguien que esté depurando / arreglando esto.

No estoy seguro de si está realmente relacionado, pero descubrí que podría haber un AttributeError debido a que mail.outbox no se configuró en primer lugar, pero esto está relacionado con cambiar el entorno mientras pytest-django gira.
Ref: https://github.com/pytest-dev/pytest-django/pull/708

Actualmente tengo el problema, ese buzón de correo no está vacío :(
Es el último argumento de la función de prueba.

EDITAR: llamo mailoutbox.clear() antes del código de prueba real como trabajo de una ronda.

@jedie
¿Puede proporcionar un caso de prueba reproducible? Una prueba fallida para pytest-django sería la mejor, por supuesto.

¿Relacionado con # 708? (es decir, hurgue en el código que toca allí)

He creado un caso de prueba trivial que reproduce el problema (al menos de la forma en que lo estoy experimentando): https://github.com/pytest-dev/pytest-django/compare/master...koniiiik : 589- mailoutbox-is-not-django-core-mail-outbox? expand = 1

Por cómo he usado mailoutbox , también sería muy útil poder tener mailoutbox.clear() realidad borrados tanto mailoutbox como mail.outbox . Si mailoutbox is mail.outbox , entonces alguien podría borrar la bandeja de salida antes de ejecutar el código que se supone que genera un número específico de correos electrónicos (es decir, digamos 1 correo electrónico).

No estoy seguro si esto está relacionado con este problema, pero el accesorio mailoutbox no coincide con el comportamiento de mail.outbox en mi prueba. No recopila los correos electrónicos enviados:

(Pdb) mail.outbox
[<django.core.mail.message.EmailMultiAlternatives object at 0x7f6d864cb198>]
(Pdb) mailoutbox
[]
(Pdb)

No estoy seguro si esto está relacionado con este problema, pero el accesorio mailoutbox no coincide con el comportamiento de mail.outbox en mi prueba. No recopila los correos electrónicos enviados:

(Pdb) mail.outbox
[<django.core.mail.message.EmailMultiAlternatives object at 0x7f6d864cb198>]
(Pdb) mailoutbox
[]
(Pdb)

Mismo.
mail.outbox contiene un mensaje mientras que mailoutbox está vacío.
La versión de pytest-django es 3.9.0.

Tengo el mismo problema.

Si uso el accesorio como este, falla:

def test_send_foo_mail(mailoutbox, user_client, foo):

Así funciona:

def test_send_foo_mail(user_client, foo, mailoutbox):

Me tomó mucho tiempo descubrirlo. Me gustaría ayudar a depurar esto. Miré la implementación, pero no tengo ni idea de cómo depurar esto.

Relacionado: https://stackoverflow.com/questions/66846621/mailoutbox-works-only-if-last-fixture

Experimentar el mismo comportamiento que el comentarista anterior. Usarlo así no funciona:

def test_command_and_email(
    mailoutbox, argument, time_machine, mocker 
):

Pero todo funciona como se ejecutó si lo pongo en el último lugar.

def test_command_and_email(
    argument, time_machine, mocker, mailoutbox
):

El argumento argument también es un accesorio que usa db accesorio, así que supongo que esa es la razón principal de este comportamiento.
Estoy usando pytets-django 4.3.0

¿Fue útil esta página
0 / 5 - 0 calificaciones

Temas relacionados

clintonb picture clintonb  ·  4Comentarios

koxu1996 picture koxu1996  ·  3Comentarios

AndreaCrotti picture AndreaCrotti  ·  5Comentarios

rlskoeser picture rlskoeser  ·  7Comentarios

ojake picture ojake  ·  6Comentarios