Testing Django email backend
Asked Answered
J

4

14

In my settings.py, I put:

EMAIL_BACKEND = 'mailer.backend.DbBackend'

So even when importing from from django.core.mail import send_mail, the send_mail function still queues up the email in the database instead of sending it immediately.

It works just fine when actually running the website, but when testing the website, and accessing some webpages that trigger emails, emails are no longer queued anymore:

def test_something(self):
    ...
    # Check no emails are actually sent yet
    self.assertEquals(len(mail.outbox), 0) # test fails here -- 2 != 0

    # Check queued emails.
    messages = Message.objects.all()
    self.assertEquals(messages.count(), 2) # test would also fail here -- 0 != 2
    ...

How come it doesn't seem to be using the backend when it is testing? (importing send_mail from mailer itself gets the tests to pass, but I can't really change the imports of other mailing apps like django-templated-email)

Jaconet answered 24/4, 2013 at 8:16 Comment(1)
@AlexanderAfanasiev yes I have got the backend working when running the website with runserver; it's just not working when doing unit tests, for whatever reason.Jaconet
N
35

According to this question django overrides the setting.EMAIL_BACKEND when testing to 'django.core.mail.backends.locmem.EmailBackend'. It's also in the django docs here.

Nickell answered 26/4, 2013 at 12:15 Comment(1)
Got it working with this answer: https://mcmap.net/q/827204/-django-test-framework-with-file-based-email-backend-server. Many thanks!!Jaconet
N
5

To properly test email with django-mailer, you need to override two settings:

  1. Make the tests to use the django-mailer backend
  2. Make the djano-mailer backend to use the test backend

If you don't set the django-mailer backend (number 2), your tests will try to send the email for real.

You also need to simulate running django-mailer's send_mail management command so that you can check mail.outbox for the correct email.

Here's an example of how to setup a test method:

from mailer.engine import send_all

@override_settings(EMAIL_BACKEND='mailer.backend.DbBackend')
@override_settings(MAILER_EMAIL_BACKEND='django.core.mail.backends.locmem.EmailBackend')
def test_email(self):
    # Code that generates email goes here.

    send_all()  # Simulates running django-mailer's send_mail management command.

    # Code to check the email in mail.outbox goes here.

This strategy makes your tests specific to django-mailer which you don't always want or need. I personally only use this setup when I'm testing specific functionality enabled by django-mailer. Otherwise, I use the default test email backend setup by django.

Noto answered 25/9, 2014 at 15:28 Comment(0)
R
3

If you really want have sending of emails (like default) via SMTP in django tests use the decorator:

from django.test.utils import override_settings    

@override_settings(EMAIL_BACKEND='django.core.mail.backends.smtp.EmailBackend')
class TestEmailVerification(TestCase):
   ...
Relic answered 18/4, 2018 at 21:43 Comment(0)
E
1

Try the following:

django.core.mail.backends.console.EmailBackend
Erasion answered 18/10, 2020 at 11:20 Comment(1)
What's the benefit to this over django.core.mail.backends.locmem.EmailBackend, as articulated in the accepted answer from seven years ago?Bidle

© 2022 - 2024 — McMap. All rights reserved.