Pytest-django: `mail.outbox` nicht gesetzt?

Erstellt am 10. Apr. 2018  ·  14Kommentare  ·  Quelle: pytest-dev/pytest-django

Hey, danke für pytest-django! Schätzen Sie all die harte Arbeit, habe es schon einige Male ohne Probleme verwendet.

Wir haben einen kleinen Haken, bei dem wir einige Dinge aktualisiert haben und plötzlich speichert mail.outbox keine E-Mails während der Tests. Ich habe versucht herauszufinden, wie genau das mailoutbox Fixture wie hier dokumentiert verwendet wird

Im Moment testen wir in einer Klasse und ich habe einige Konfigurationen ausprobiert, um mailoutbox Fixture zu bestehen. Dh ich habe die ini aktualisiert:

[pytest]
usefixtures = mailoutbox

Ich bin mir jedoch nicht ganz sicher, wie ich dieses Gerät verwenden soll. Ich habe versucht, das Positionsargument mailoutbox zu meinen Klassenmethoden hinzuzufügen, kann aber immer noch nicht darauf zugreifen. Ich bin sicher, dass mir etwas Einfaches fehlt.

Würde mich über einen Schubs in die richtige Richtung freuen – und nochmals vielen Dank für dieses Projekt!

bug

Hilfreichster Kommentar

Ich glaube, ich habe das gleiche Problem, also habe ich beschlossen, meinen Test auf einen einfachen E-Mail-Versand zu reduzieren und ihn einzeln auszuführen:

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 ----------------------------------------------

Jetzt ist der coole Teil, wenn ich die db Halterung entferne, besteht der Test. Also habe ich versucht, meine Methode django_db_setup löschen, aber ohne Erfolg ...

Ich stecke im Moment fest.

Alle 14 Kommentare

Siehe https://github.com/pytest-dev/pytest-django/blob/5da0935731d71aa347c57cd1753f51e3ba9f32d5/docs/helpers.rst#clearing -of-mailoutbox (7aee367).
(Nicht klar, ob ich das Problem richtig verstehe)

Ich glaube, ich habe das gleiche Problem, also habe ich beschlossen, meinen Test auf einen einfachen E-Mail-Versand zu reduzieren und ihn einzeln auszuführen:

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 ----------------------------------------------

Jetzt ist der coole Teil, wenn ich die db Halterung entferne, besteht der Test. Also habe ich versucht, meine Methode django_db_setup löschen, aber ohne Erfolg ...

Ich stecke im Moment fest.

Ich habe vergessen zu erwähnen, dass es im selben Projekt einige Tests gibt, bei denen das Fixture mailoutbox zu funktionieren scheint, also habe ich versucht, einen Unterschied zwischen diesen Tests und dem fehlgeschlagenen zu erkennen.
Der einzige Unterschied, den ich gefunden habe, ist die Positionierung des Arguments mailoutbox in der Testfunktion. Wenn es vor einem Fixture steht, das von dem db Fixture abhängt, funktioniert es nicht, aber es funktioniert, wenn ich es danach setze, also habe ich wohl einen Workaround gefunden.

Ich kann bestätigen, dass wir dieses Verhalten auch mit pytest-django==3.3.3 sehen

@bogdanpetrea
Danke für die Recherche/Update.
Wird für jemanden hilfreich sein, der dies debuggt/behebt.

Ich bin mir nicht sicher, ob es wirklich damit zusammenhängt, aber ich habe festgestellt, dass es möglicherweise einen AttributeError gibt, weil mail.outbox nicht gesetzt wurde - aber dies hängt mit der Änderung der Umgebung zusammen, während pytest-django hochfährt.
Ref: https://github.com/pytest-dev/pytest-django/pull/708

Ich habe aktuell das Problem, dass die Mailoutbox nicht leer ist :(
Es ist das neueste Testfunktionsargument.

EDIT: Ich rufe mailoutbox.clear() vor dem echten Testcode als Work-a-Round auf.

@jedie
Können Sie einen reproduzierbaren Testfall bereitstellen? Ein nicht bestandener Test für pytest-django wäre natürlich das Beste.

Bezogen auf #708? (dh stochern Sie in dem Code herum, den es dort berührt)

Ich habe einen trivialen Testfall erstellt, der das Problem reproduziert (zumindest so, wie ich es erlebe): https://github.com/pytest-dev/pytest-django/compare/master...koniiiik :589- mailoutbox-is-not-django-core-mail-outbox?expand=1

Nach der Art, wie ich mailoutbox , wäre es auch sehr hilfreich, mailoutbox.clear() tatsächlich sowohl mailoutbox als auch mail.outbox löschen zu können. Wenn mailoutbox is mail.outbox , dann könnte jemand den Postausgang leeren, bevor Code ausgeführt wird, der dann eine bestimmte Anzahl von E-Mails generieren soll (zB 1 E-Mail).

Ich bin mir nicht sicher, ob dies mit diesem Problem zusammenhängt, aber das mailoutbox Gerät stimmt nicht mit dem Verhalten von mail.outbox in meinem Test überein. Es werden keine gesendeten E-Mails gesammelt:

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

Ich bin mir nicht sicher, ob dies mit diesem Problem zusammenhängt, aber das mailoutbox Gerät stimmt nicht mit dem Verhalten von mail.outbox in meinem Test überein. Es werden keine gesendeten E-Mails gesammelt:

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

Dasselbe.
mail.outbox enthält eine Nachricht, während mailoutbox leer ist.
pytest-django-Version ist 3.9.0.

Ich habe das gleiche Problem.

Wenn ich das Gerät so verwende, schlägt es fehl:

def test_send_foo_mail(mailoutbox, user_client, foo):

So funktioniert es:

def test_send_foo_mail(user_client, foo, mailoutbox):

Ich habe viel Zeit gebraucht, um es zu entdecken. Ich möchte helfen, dies zu debuggen. Ich habe mir die Implementierung angeschaut, aber ich habe keine Ahnung, wie ich das debuggen soll.

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

Erlebe das gleiche Verhalten wie der vorherige Kommentator. So zu verwenden funktioniert nicht:

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

Aber alles funktioniert wie gewünscht, wenn ich es nur an letzter Stelle setze.

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

Argument argument ist auch ein Fixture, das db Fixture verwendet, also denke ich, dass dies der Hauptgrund für dieses Verhalten ist.
Ich verwende pytets-django 4.3.0

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen