pytest-django icon indicating copy to clipboard operation
pytest-django copied to clipboard

_dj_autoclear_mailbox ends quite often with AttributeError: module 'django.core.mail' has no attribute 'outbox'

Open mcepl opened this issue 2 years ago • 7 comments

When running the test suite for whitenoise plenty of tests ends with the following error (using pytest-6.2.5, pytest-django-4.5.2):

[   31s] _______ ERROR at setup of test_last_modified_not_set_when_mtime_is_zero ________
[   31s]
[   31s]     @pytest.fixture(scope="function", autouse=True)
[   31s]     def _dj_autoclear_mailbox() -> None:
[   31s]         if not django_settings_is_configured():
[   31s]             return
[   31s]
[   31s]         from django.core import mail
[   31s]
[   31s] >       if mail.outbox:
[   31s] E       AttributeError: module 'django.core.mail' has no attribute 'outbox'
[   31s]

When reading on the mail.outbox I found that it doesn’t exist quite often, so this fixture has protection against it. When I apply this patch:

---
 pytest_django/plugin.py |    3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

--- a/pytest_django/plugin.py
+++ b/pytest_django/plugin.py
@@ -502,7 +502,8 @@ def _dj_autoclear_mailbox() -> None:

     from django.core import mail

-    del mail.outbox[:]
+    if hasattr(mail, "outbox"):
+        del mail.outbox[:]


 @pytest.fixture(scope="function")

Tests pass without a problem.

mcepl avatar Feb 22 '22 21:02 mcepl

Based on Django documentation:

During test running, each outgoing email is saved in django.core.mail.outbox. This is a list of all EmailMessage instances that have been sent. The outbox attribute is a special attribute that is created only when the locmem email backend is used. It doesn’t normally exist as part of the django.core.mail module and you can’t import it directly.

Could you please add a test to show in what condition the above mentioned error happens?

hramezani avatar Feb 22 '22 21:02 hramezani

The above error is from running test suite of https://github.com/evansd/whitenoise

Complete build log contains records of all packages used and steps taken.

mcepl avatar Feb 22 '22 22:02 mcepl

@evansd Does this whole ticket make sense to you?

mcepl avatar Feb 24 '22 23:02 mcepl

This sounds like an incompatibility between the versions of Django and pytest-django being used and nothing specific to whitenoise.

evansd avatar Feb 25 '22 09:02 evansd

Im having the Same errors, i created a custom django_db_setup() fixture and give my database definition to the settings.configure(DATABASES=) Im using pytest 7.0.1, pytest-django 4.2.5
I dont even use The Django email stuff, its just a basic graphene application.

cfarsbot avatar Mar 09 '22 20:03 cfarsbot

I see the same issue occurring recently. Note that the error occurs in the _dj_autoclear_mailbox test fixture that is marked with autouse=True. So it occurs with any test.

I my case, it occurs in a project in which Django is set up manually because the project only needs to be able to generated html based on Django templates. For testing, the Django instance is set up as follows:

@fixture(autouse=True, scope="session")
def django():
    import django
    from django.conf import settings

    settings.configure(
        TIME_ZONE="Europe/Brussels",
        USE_I18N=True,
        USE_L10N=False,
    )
    django.setup()

Note that I can avoid the issue by adding the following in my root conftest:

@fixture(scope="function", autouse=True)
def _dj_autoclear_mailbox() -> None:
    # Override the `_dj_autoclear_mailbox` test fixture in `pytest_django`.
    pass

wouter-vdb avatar Oct 02 '22 12:10 wouter-vdb

Reproduced with Django 4.2.7 with no settings configuration. For me, I happened to have Django in my venv but had not configured a settings in this particular test slice and ran into the exception.

Thanks @wouter-vd, your workaround did indeed fix it!

phillipuniverse avatar Nov 15 '23 04:11 phillipuniverse