如何在 Django 中测试 send_mail?

Posted

技术标签:

【中文标题】如何在 Django 中测试 send_mail?【英文标题】:How to test send_mail in Django? 【发布时间】:2016-05-23 16:40:29 【问题描述】:

使用 Django 1.7 和 Python 2.7。

我想测试邮件是否发送,邮件内容是否正确。

我尝试使用 django.core.mail 的发件箱,但无济于事。 我也可以只获取标准输出(因为我在运行测试时可以在控制台中看到邮件)?

models.py

class User(AbstractBaseUser, PermissionsMixin):
    USERNAME_FIELD = 'email'

    email = models.EmailField(max_length=255, unique=True)
    is_staff =  models.BooleanField(default=False)
    org = models.ForeignKey('Org', null=True, blank=True,
        on_delete=models.SET_NULL)

    def __unicode__(self):
        return self.email

    @staticmethod
    def send_password_token(email):
        user = get_object_or_404(User, email=email)
        token = Token.objects.get(user=user)
        message_body = 'Your password reset token:\n\n\t%s' % token.key
        send_mail('Password reset:', message_body,
            settings.FROM_EMAIL, [email], fail_silently=False)

tests.py

class UserModelTest(TestCase):
    def setUp(self):
        self.user = User.objects.create_user(email='user@info.com',
            password='0000')

    @override_settings(EMAIL_BACKEND = 'django.core.mail.backends.console.EmailBackend')
    def test_send_password_token(self):
        """
        Sends a password reset mail with users authentication token.
        """
        token = Token.objects.get(user=self.user)
        User.send_password_token(self.user.email)

【问题讨论】:

你见过example in the docs吗?您应该删除 override_settings 装饰器。然后django会自动使用locmem邮箱后台,把邮箱放到发件箱里供你查看。 当你使用控制台后端时,邮件只会被发送到标准输出,而不是来自 django.core.mail 邮箱。使用 locmem 后端。 docs.djangoproject.com/en/1.9/topics/email/#in-memory-backend 【参考方案1】:

感谢@Alasdair 的解决方案。原来这很简单。只需删除 override_settings 并导入发件箱。

tests.py

from django.core.mail import outbox

class UserModelTest(TestCase):
    def setUp(self):
        self.user = User.objects.create_user(email='user@info.com',
            password='0000')

    def test_send_password_token(self):
        """
        Sends a password reset mail with users authentication token.
        """
        token = Token.objects.get(user=self.user)
        User.send_password_token(self.user.email)
        self.assertEqual(len(outbox), 1)
        self.assertEqual(outbox[0].subject, 'Password reset:')
        self.assertEqual(outbox[0].from_email, <insert_from_email>)
        self.assertEqual(outbox[0].to, [<insert_list_of_to_emails>])
        self.assertEqual(outbox[0].body,
            'Your password reset token:\n\n\t%s' % token.key)

【讨论】:

这在 Django 2 中可能已经改变——现在导入似乎是 from django.core import mail 并且发件箱像 mail.outbox 一样被检查

以上是关于如何在 Django 中测试 send_mail?的主要内容,如果未能解决你的问题,请参考以下文章

python测试开发django-28.发送邮件

python测试开发django(28)--发送附件EmailMessage

django-28.发送邮件send_mail

Django,send_mail,没有足够的值来解包

Django 收到错误:send_mail() 在发送邮件时收到了意外的关键字参数“fail_silently”

测试 Django 电子邮件后端