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)

wrongusername
  • 18,564
  • 40
  • 130
  • 214
  • @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. – wrongusername Apr 24 '13 at 17:45

4 Answers4

33

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.

Community
  • 1
  • 1
Jacob Harding
  • 631
  • 7
  • 15
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.

Ben Konrath
  • 423
  • 4
  • 8
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):
   ...
andilabs
  • 22,159
  • 14
  • 114
  • 151
1

Try the following:

django.core.mail.backends.console.EmailBackend
Jeremy Caney
  • 7,102
  • 69
  • 48
  • 77
Artem Uk
  • 46
  • 2
  • What's the benefit to this over `django.core.mail.backends.locmem.EmailBackend`, as articulated in [the accepted answer](https://stackoverflow.com/a/16236241/3025856) from seven years ago? – Jeremy Caney Oct 18 '20 at 20:07