How to write test case for sending email

Viewed 382

Here is the simple view for creating user and staff model.After creating user and staff, it sends the html email to the user's email to fill up the details and the view works fine. Now I want to write test case for this view and tried like this below but i got stuck on how can i write test to check whether the email will be sent or not after saving staff model, to the users. models.py

class Staff(models.Model):
    user = models.OneToOneField(get_user_model(), on_delete=models.CASCADE, related_name='staff')
    name = models.CharField(max_length=255, blank=True, null=True)
    organization = models.ForeignKey(Organization, on_delete=models.SET_NULL,related_name='staff')
    position = models.ForeignKey(Position, on_delete=models.SET_NULL,related_name='staff')
    .......

views.py

def register_staff(request):
    form = RegisterStaffForm()
    if request.method == 'POST':
        form = RegisterStaffForm(request.POST)
        if form.is_valid():
            name = form.cleaned_data['name']
            organization = form.cleaned_data['organization']
            position = form.cleaned_data['position']
            ......
            user = form.save(commit=False)
            user.is_staff = True
            user.is_active = True
            user.save()

            # creating staff model with user data

            Staff.objects.create(user=user, name=name, organization=organization, position=position,....)

            # sending html_email to the user
            config = EmailConfiguration.objects.order_by('-date').first()
            backend = EmailBackend(host=config.email_host, port=config.email_port, username=config.email_host_user,
                                   password=config.email_host_password, use_tls=config.email_use_tls)

            subject, from_email, to = "Staff Details", config.email_host_user, user.email
            text_content = "Staff Details "
            site = get_current_site(request)
            html_content = render_to_string('send_email.html',
                                            {'user': user, 'site_domain': site,})
            msg = EmailMultiAlternatives(subject, text_content, from_email, [to],connection=backend)
            msg.attach_alternative(html_content, "text/html")
            msg.send()

tests.py

class StaffTestCase(TestCase):

    def setUp(self):
        self.position = Position.objects.create(title='Developer')
        self.org = Organization.objects.create(name='name')
        self.user = get_user_model().objects.create_user(username='username01',password='Admin@321',email='abc@xyz.com',is_staff=True)
        self.staff = Staff.objects.create(user=self.user,position=self.position,organization=self.org,name='Julia')

        self.client = Client()

    def test_view_staffs(self):
        self.client.login(username='username01', password='Admin@321')
        response = self.client.get(reverse('app:view_staff_users'))
        self.assertEqual(response.status_code, 200)

    def add_staff(self):
        self.client.login(username='username01', password='Admin@321')
        url = reverse('app:register_staff')
        response = self.client.post(url, {'user': self.user,'organization':'name1','position':'Designer','name':'Mark'})
        self.assertEqual(response.status_code, 302)

    def check_email_will_sent_or_not(self):
     ??
1 Answers

Django provides tools to test the sending of emails, but from my understanding, these only work with the default email backend configured in your settings file.

That leaves you with four options:

  1. figure out if you can monkeypatch your view to use locmem backend in testing
  2. mock EmailBackend in your register_staff view and check if its send_messages function is called.
  3. spin up a dummy SMTP server and check if it receives the messages
  4. use valid credentials to actually send the emails to addresses you control and check if the email is received

The options 3 & 4 give you the most confidence that your email sending really works, but they might turn out to be slow and brittle and actually test the email sending code of Django itself. I would go with option 2.

Related