【问题标题】:Django - testing emails with the outbox using post_officeDjango - 使用 post_office 测试带有发件箱的电子邮件
【发布时间】:2019-10-18 15:44:30
【问题描述】:

我正在为一个使用django-post_office 包来实现其大部分电子邮件功能的应用程序编写测试。

默认的django.core.mail 库包含大量有用的工具,用于测试是否真的有电子邮件正在发送。 (在测试期间没有实际发送任何内容)

class TestFunctionThatSendsEmail(Testcase):

   @override_settings(
        EMAIL_BACKEND='django.core.mail.backends.locmem.EmailBackend'
   )
   def test_function_sends_email(self):
       self.assertEqual(len(outbox), 0)
       run_function_that_calls_email()
       self.assertEqual(len(outbox), 1)
       ...
       # other tests

但是,我们函数中的电子邮件是使用 django-post_office mail.send() 函数发送的

# priority now to make sure that they are being sent right away
mail.send(
        sender=sender,
        recipients=to,
        context=context,
        template=template_name,
        priority='now',
    )

这会导致上述测试失败,因为某些原因电子邮件没有最终进入发件箱。

奇怪的是,如果我将 EMAIL_BACKEND 更改为 django.core.mail.backends.console.EmailBackend,电子邮件会显示在我的终端中,因此它正在监听 EMAIL_BACKEND 设置。

我尝试在django-post_office github 中寻找替代方法/功能来测试此功能,但我只能找到检查电子邮件是否保存到数据库并验证其状态的建议。 (我做过并且工作过)但是 django 似乎无法检测到任何实际发送的电子邮件这一事实让我有点紧张。

有没有人知道让django-post_office 发送的电子邮件出现在发件箱中的方法,或者,如果不可能,有一种方法可以确保它们确实被发送? (除了检查数据库)

【问题讨论】:

  • 你找到答案了吗?我有同样的问题。
  • 不幸的是我没有。我最终模拟了我们的“send_email”函数(它本身包含对 post_office_mail.send() 函数的调用)并验证调用是用正确的参数进行的——因此隐含地相信邮局包可以正常工作。
  • 另一种选择是从Email模型中获取email对象,并测试self.assertEqual(email.status, STATUS.sent)。这至少告诉您self.email_message()dispatch() 下返回。

标签: python django django-email django-postoffice


【解决方案1】:

问题在于django-post_office 将邮件后端存储在Email 对象中:

class Email(models.Model):
    backend_alias = models.CharField(_("Backend alias"), blank=True, default='',
                                     max_length=64)

dispatch() 被调用时,它使用这个后端。

创建电子邮件时,DPO 会覆盖 create() 以从 def get_available_backends() 设置后端,这会在 settings conf 中查找后端。

这意味着使用@override_settings(EMAIL_BACKEND='django.core.mail.backends.locmem.EmailBackend') 不会正确设置Email 对象中的backend_alias

根据调度测试,您需要在创建对象时手动执行此操作:

def test_dispatch(self):
    """
    Ensure that email.dispatch() actually sends out the email
    """
    email = Email.objects.create(to=['to@example.com'], from_email='from@example.com',
                                 subject='Test dispatch', message='Message', backend_alias='locmem')
    email.dispatch()
    self.assertEqual(mail.outbox[0].subject, 'Test dispatch')

如果您使用mail.send(),您可以简单地将mail.send(backend='locmem') 作为参数传递;确保您的POST_OFFICE 设置中有locmem': 'django.core.mail.backends.locmem.EmailBackend'

【讨论】:

    【解决方案2】:

    我遇到了与您描述的相同的问题,并通过将 DEFAULT_PRIORITY 设置为 'now' 来修复它:

    class TestFunctionThatSendsEmail(Testcase):
    
       @override_settings(
            POST_OFFICE={
                'BACKENDS': {'default': 'django.core.mail.backends.locmem.EmailBackend'},
                'DEFAULT_PRIORITY': 'now',
            }
       )
       def test_function_sends_email(self):
           self.assertEqual(len(outbox), 0)
           run_function_that_calls_email()
           self.assertEqual(len(outbox), 1)
           ...
           # other tests
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-11-10
      • 1970-01-01
      • 1970-01-01
      • 2013-04-17
      • 2016-01-08
      • 1970-01-01
      • 2011-04-13
      • 1970-01-01
      相关资源
      最近更新 更多