2013-03-19 97 views
2

由于主题中的换行符,独立调用send_mail函数将导致BadHeaderError异常。为什么这个Django测试通过?

我希望这个test_newline_causes_exception也会失败,但事实并非如此。这是在Django 1.3中。有任何想法吗?

from django.core.mail import send_mail 
from django.utils import unittest 

class EmailTestCase(unittest.TestCase): 

    def test_newline_causes_exception(self): 
     send_mail('Header\nInjection', 'Here is the message.', '[email protected]', 
        ['[email protected]'], fail_silently=False) 

编辑:该新的测试表明,当send_mail在测试中所使用的报头校验码(django.core.mail.message.forbid_multi_line_headers)不被调用。

from django.core.mail import send_mail, BadHeaderError, outbox 
from django.utils import unittest 

class EmailTestCase(unittest.TestCase): 

    def test_newline_in_subject_should_raise_exception(self): 

     try: 
      send_mail('Subject\nhere', 'Here is the message.', 
         '[email protected]', ['[email protected]'], fail_silently=False) 
     except BadHeaderError: 
      raise Exception 

     self.assertEqual(len(outbox), 1) 

     self.assertEqual(outbox[0].subject, 'Subject here') 

结果:

AssertionError: 'Subject\nhere' != 'Subject here' 
+0

它会在django shell中抛出异常吗? – alecxe 2013-03-19 21:46:57

+0

@AlexanderAfanasiev是的。 – Alex 2013-03-19 21:47:39

+3

Django在测试阶段替换正常的电子邮件后端和测试。这可能是一个原因。请检查django.core.mail.outbox中是否存在错误,或换句话说,是否实际发送了消息。请参阅https://docs.djangoproject.com/en/1.3/topics/testing/#e-mail-services。 – alecxe 2013-03-19 21:57:40

回答

2

我发现,这个问题已得到修复在Django 1.5。测试邮件后端(locmem.py)现在执行与标准后端相同的头部清理。

https://code.djangoproject.com/ticket/18861

https://github.com/django/django/commit/8599f64e54adfb32ee6550ed7a6ec9944034d978

EDIT

我发现在Django版本< 1.5用于测试头的验证一种解决方法。

使用get_connection方法加载控制台后端,该后端执行与生产后端相同的验证。

感谢亚历山大Afanasiev指出我在正确的方向。

connection = get_connection('django.core.mail.backends.console.EmailBackend') 
send_mail('Subject\nhere', 
      'Here is the message.', 
      '[email protected]', 
      ['[email protected]'], 
      fail_silently=False, 
      connection=connection) 
+1

因此,对于django <1.5,解决方法是模拟'django.core.mail.backends.locmem.EmailBackend.send_messages'方法并为每条消息调用'message.message()',对吗?那么我认为它应该被接受为你的问题的答案。 – alecxe 2013-03-20 06:38:44

+0

@AlexanderAfanasiev我找到了一个不需要嘲笑locmem的解决方案。看我的编辑。谢谢你的帮助! – Alex 2013-03-20 20:59:41

+0

很高兴知道,谢谢! – alecxe 2013-03-21 07:59:25

2

你没有真正测试什么。测试意味着检查BadHeaderError是否已被提出。如果断言测试是错误的,测试将失败。你可以这样做 -

def test_newline_causes_exception(self) 
    error_occured = False 
    try: 
     send_mail('Header\nInjection', 'Here is the message.', '[email protected]', 
        ['[email protected]'], fail_silently=False) 
    except BadHeaderError: 
     error_occured = True 

    self.assertTrue(error_ocurred) 

我还没有测试过它。但它应该工作。

PS:from django.core.mail import send_mail, BadHeaderError

+0

谢谢。我明白你在说什么,但我写的测试仍然会失败,对吧?就像我会在'raise Exception'中加入一行一样会失败。 – Alex 2013-03-19 22:31:46

+0

也许,我不确定你是如何实现它的。可能有很多其他的条件会影响它(例如,邮件传递延迟等)。我只是知道,如果你想检查是否引发'BadHeaderError',你应该检查一下,而不是其他方式。 – 2013-03-19 22:36:37

相关问题