How to test EmailMessage .send() with backend modified by EmailBackend

Viewed 258

How to test emails send via EmailMessage .send() when email backend is set by EmailBackend object? As the backend is modified inside this function mail.outbox does not store any outgoing emails. What would be the most Django way of approaching this?

function in question:

def send_email_to_users(email_message_obj):
    recipients = [user.email for user in email_message_obj.addressees.all()]
    ap = Admin_Profile.objects.get(id=1)
    backend = EmailBackend( host=ap.email_host,
                            port=ap.email_port,
                            username=ap.email_host_user,
                            password=ap.email_host_password,
                            use_tls=ap.email_use_tls,
                            fail_silently=False)

    email = EmailMessage(   subject=email_message_obj.title,
                            body=email_message_obj.body,
                            from_email=email_message_obj.email_from,
                            to=recipients,
                            connection=backend)
    email.send()

test:

class Testsend_email_to_users(TestCase):
    def setUp(self):
        User.objects.create_superuser(
            username='admin', email='jlennon@beatles.com', password='glassonion')
    @override_settings(EMAIL_BACKEND='django.core.mail.backends.locmem.EmailBackend')
    def test_one_email(self):
        '''should send one email'''
        Admin_Profile.objects.create(
            user=User.objects.all().first(),
            email_host=settings.TEST_EMAIL_HOST,
            email_port=settings.TEST_EMAIL_PORT,
            email_host_user=settings.TEST_EMAIL_HOST_USER,
            email_host_password=settings.TEST_EMAIL_HOST_PASSWORD,
            email_use_tls=True,
        )
        u1 = mixer.blend(User, email=settings.ADMIN_EMAIL)
        email_message = Email_Message.objects.create(
            title='test title',
            body='test body',
            email_from=settings.TEST_EMAIL_HOST_USER,
        )
        email_message.addressees.add(u1)

        send_email_to_users(email_message)

        # should send one email
        self.assertEqual(len(mail.outbox), 1)

result of the test:

>       self.assertEqual(len(mail.outbox), 1)
E       AssertionError: 0 != 1

models.py:

class Admin_Profile(models.Model):
    ...
    email_host = models.CharField(max_length=100, blank=True)
    email_port = models.IntegerField(null=True, blank=True)
    email_host_user = models.EmailField(
        max_length=70, null=True, blank=True)
    email_host_password = models.CharField(max_length=100, blank=True)
    email_use_tls = models.BooleanField(null=True, blank=True)

class Email_Message(models.Model):
    title = models.CharField(max_length=78)
    body = models.TextField()
    email_from = models.EmailField()
    addressees = models.ManyToManyField(settings.AUTH_USER_MODEL)
    timestamp = models.DateTimeField(auto_now_add=True)
    ...

Notes:

  • send_email_to_users is functional and sends 'real' emails;

  • test_settings.py contains:

  • all other tests that use django.core.mail.send_mail pass the tests and are captured in mail.outbox;

  • additionally, test method was decorated with: @override_settings(EMAIL_BACKEND='django.core.mail.backends.locmem.EmailBackend'), but as the backend is specifically changed inside the function this has no impact;

  • test_one_email sends 'real' email but fails on mail.outbox

Versions: Python 3.5.2, Django 2.2.9, pytest 4.0.2, pytest-django 3.4.4

0 Answers
Related