Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

mail.outbox not being set? #589

Open
ckcollab opened this issue Apr 10, 2018 · 14 comments
Open

mail.outbox not being set? #589

ckcollab opened this issue Apr 10, 2018 · 14 comments
Labels

Comments

@ckcollab
Copy link

Hey there, thanks for pytest-django! Appreciate all of the hard work, have used it quite a few times with no problems.

We're running into a bit of a snag where we upgraded some things and suddenly mail.outbox isn't retaining emails during tests. I've tried to figure out how exactly to use the mailoutbox fixture as documented here but I am having trouble using this.

Right now we're testing in a class and I have tried quite a few configurations to pass mailoutbox fixture. I.e. I updated the ini:

[pytest]
usefixtures = mailoutbox

Not exactly sure how to use that fixture though, I tried adding the positional argument mailoutbox to my class methods, still not able to access it.. I am sure I am missing something simple.

Would appreciate a push in the right direction -- and again, thanks so much for this project!

@blueyed
Copy link
Contributor

blueyed commented Apr 14, 2018

@bogdanpetrea
Copy link

bogdanpetrea commented Jun 19, 2018

I think I'm having the same issue, so I decided to strip down my test to a basic email sending and ran it individually:

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="test@mail.com",
        to=['john@awesomecompany0.com']
    )

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

Now the cool part is if I remove the db fixture, the test passes. So I tried deleting my django_db_setup method, but to no avail...

I'm stuck at the moment.

@bogdanpetrea
Copy link

I forgot to mention there are some tests, in the same project, where the mailoutbox fixture seems to work, so I tried to spot any difference between those tests and the one that fails.
The only difference I found is the positioning of the mailoutbox argument in the test function. If it's before any fixture that depends on the db fixture it doesn't work, but it works if I put it after, so I guess I found a workaround.

@oppianmatt
Copy link

I can confirm we are seeing this behaviour too with pytest-django==3.3.3

@blueyed
Copy link
Contributor

blueyed commented Jul 31, 2018

@bogdanpetrea
Thanks for the investigation / update.
Will be helpful for somebody debugging/fixing this.

@blueyed blueyed added the bug label Jul 31, 2018
@blueyed
Copy link
Contributor

blueyed commented Mar 9, 2019

Not sure if it is realy related, but I've found that there might be an AttributeError due to mail.outbox not being set in the first place - but this is related to changing the environment while pytest-django spins up.
Ref: #708

@jedie
Copy link

jedie commented Apr 1, 2019

I have currently the problem, that mailoutbox is not empty :(
It's the latest test function argument.

EDIT: I call mailoutbox.clear() before real test code as work-a-round.

@blueyed
Copy link
Contributor

blueyed commented Apr 1, 2019

@jedie
Can you provide a reproducible test case? A failing test for pytest-django would be the best, of course.

Related to #708? (i.e. poke around the code that it touches there)

@koniiiik
Copy link

koniiiik commented Aug 30, 2019

I've created a trivial test case that reproduces the issue (at least the way I'm experiencing it): https://github.com/pytest-dev/pytest-django/compare/master...koniiiik:589-mailoutbox-is-not-django-core-mail-outbox?expand=1

@MicahLyle
Copy link

From how I've used mailoutbox, it would also be very helpful to be able to have mailoutbox.clear() actually clear both mailoutbox and mail.outbox. If mailoutbox is mail.outbox, then someone could clear the outbox before running code that is then supposed to generate a specific number of emails (I.E. say 1 email).

@jshields
Copy link

Not sure if this is related to this issue, but the mailoutbox fixture does not match the behavior of mail.outbox in my test. It's not collecting sent emails:

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

@sanjioh
Copy link

sanjioh commented Jun 19, 2020

Not sure if this is related to this issue, but the mailoutbox fixture does not match the behavior of mail.outbox in my test. It's not collecting sent emails:

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

Same.
mail.outbox contains a message while mailoutbox is empty.
pytest-django version is 3.9.0.

@guettli
Copy link
Contributor

guettli commented Mar 29, 2021

I have the same issue.

If I use the fixture like this it fails:

def test_send_foo_mail(mailoutbox, user_client, foo):

Like this it works:

def test_send_foo_mail(user_client, foo, mailoutbox):

It took me a lot of time to discover it. I would like to help to debug this. I looked at the implementation, but I don't have a clue how to debug this.

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

@FerenetsRoman
Copy link

FerenetsRoman commented Jun 18, 2021

Experiencing the same behavior as previous commentator. Using it like this doesn't work:

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

But everything works as exected if I just put it at the last place.

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

Argument argument is also a fixture that uses db fixture, so I guess that's the main reason of this behavior.
I'm using pytets-django 4.3.0

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests