1

Django 2.0.6

I have some unit tests in my Django app. One of the tests needs to verify that emails are sent. How can I achieve this?

I read the django docs about testing email sending and email sending in generall via django.core.mail but somehow im still not understanding what is happening and why it is happening the way it does.

Hopefully I can explain it as precisely as possible, so here we go:

In my testcase I have a instance and call a function with it. The called function is creating and formating an E-Mail instance and is sending it via Email.send(email, '', '', subject, content) After the function call is finished I use the mail.outbox to check if there is an email but there isn't, but why? If I try to do it manually via mail.send_mail(...) and check the outbox afterwards, it works. I also have checked via print satements that the function which should be called, is actually called.

All I want is to see is that the email has been succesfully sent.

Here is my code

def test_send_email_to_teacher(self):
    # Generate test data
    self.instance.send_email_to_teacher()
    print(len(mail.outbox))
    #self.assertEqual(len(mail.outbox), 1)

That's the function which is

def send_email_to_teacher(self):
    for group in self.practicegroup_set.all():
    group.send_email_to_teacher()

And this function calls this one:

def send_email_to_teacher(self):
    link = reverse('sometext', args=[self.get_preferences_token_for_teacher()])
    link = settings.BASE_URL + str(link)
    Email.send_preferences_link(self.teacher.email, link)

And this function calls this one:

def send_preferences_link(email, link):
    content = Email.load_email_template('sometext')
    content = content.replace('##LINK##', link)
    subject = "also some text"
    Email.send(email, '', '', subject, content)

Email instance is:

class Email(models.Model):
    to = models.TextField(null=True, blank=True)
    cc = models.TextField(null=True, blank=True)
    bcc = models.TextField(null=True, blank=True)
    sender = models.CharField(max_length=255)
    subject = models.CharField(max_length=255)
    text = models.TextField(null=True, blank=True)
    date_created = models.DateTimeField(auto_now_add=True, null=True, blank=True)
    date_send = models.DateTimeField(null=True, blank=True)

the Email "send" function(method of class Email):

def send(to, cc, bcc, subject, content):
    email = Email()
    email.to = to
    email.cc = cc
    email.bcc = bcc
    email.subject = subject
    email.text = content
    email.sender = settings.EMAIL_SENDER
    email.save()
  • You haven't shown what `Email` is. – Alasdair Aug 23 '18 at 13:03
  • Your first function calls `send_email_to_teachers_preferences_link()` but that's not the name of one of the other functions you show. Also please give unit tests names starting with `test_`, and not any non-test functions. – RemcoGerlich Aug 23 '18 at 13:04
  • I don't understand what the `send` function is. Is it a method of the `Email` class? If so you should show it like that. The function simply saves an `Email()` instance to the database, so it's not clear why you expect that to send an email. To actually send an email, use [`send_mail`](https://docs.djangoproject.com/en/2.1/topics/email/#send-mail) or something similar. – Alasdair Aug 23 '18 at 13:35
  • Maybe [this](https://stackoverflow.com/a/3728540/5312750) will help. – Sachin Aug 23 '18 at 14:31

1 Answers1

0

I have the solution but I'm not sure how to post it in here but anyway. The problem was as the user Alasdair mentioned my send method just saved the Email Instance to the database and didn't actually send it. So I had to retrieve the instance from the database and send it via send_mail:

def test_send_email_to_teachers_preferences_link(self)
        returnvalue = self.sem_18s_bsc_pp1.send_email_to_teacher()
        email = Email.objects.get(subject="sometext")
        mail.send_mail(
            email.subject,
            email.text,
            'test@test.de',
            ['jj@jj.de'],
            fail_silently=False,
        )
        self.assertEqual(len(mail.outbox), 1)

This works. Thank you very much.