我怎样才能unit testingDjango的消息?

在我的Django应用程序中,我试图编写一个unit testing来执行一个动作,然后检查响应中的消息。

据我所知,没有这样做的好方法。

我正在使用CookieStorage存储方法,我想要做类似于以下的事情:

response = self.client.post('/do-something/', follow=True) self.assertEquals(response.context['messages'][0], "fail.") 

问题是,我所有的回报是

 print response.context['messages'] <django.contrib.messages.storage.cookie.CookieStorage object at 0x3c55250> 

我怎么能把这个变成有用的东西呢,还是我做错了?

谢谢Daniel

我做了一个实验来testing这个。 我将其中一个项目中的MESSAGE_STORAGE设置更改为'django.contrib.messages.storage.cookie.CookieStorage'并执行了我编写的用于检查消息的testing。 有效。

与您所做的主要区别在于我检索邮件的方式。 见下文:

 def test_message_sending(self): data = dict(...) response = self.client.post(reverse('my_view'), data) messages = self.user.get_and_delete_messages() self.assertTrue(messages) self.assertEqual('Hey there!', messages[0]) 

可能是值得一试的。

我发现了一个非常简单的方法:

 r = self.client.post('/foo/') m = list(r.context['messages']) self.assertEqual(len(m), 1) self.assertEqual(str(m[0]), 'my message') 

(我使用基于会话的后端消息)

如果您需要检查没有上下文的回复中的消息,可以使用以下内容(谢谢@benjaminGolder)

 messages = list(r.wsgi_request._messages) self.assertEqual(len(messages), 1) self.assertEqual(str(messages[0]), 'my message') 

后备存储不支持索引,但是它是可迭代的。

这适用于我(显示所有消息):

 print [m.message for m in list(response.context['messages'])] 

另外这里有几个实用的方法,我在从Django的TestCaseinheritance的testing类中。 如果您希望将它们作为函数,请删除self参数,并用self.fail()replaceself.fail()

 def assert_message_count(self, response, expect_num): """ Asserts that exactly the given number of messages have been sent. """ actual_num = len(response.context['messages']) if actual_num != expect_num: self.fail('Message count was %d, expected %d' % (actual_num, expect_num)) def assert_message_contains(self, response, text, level=None): """ Asserts that there is exactly one message containing the given text. """ messages = response.context['messages'] matches = [m for m in messages if text in m.message] if len(matches) == 1: msg = matches[0] if level is not None and msg.level != level: self.fail('There was one matching message but with different' 'level: %s != %s' % (msg.level, level)) return elif len(matches) == 0: messages_str = ", ".join('"%s"' % m for m in messages) self.fail('No message contained text "%s", messages were: %s' % (text, messages_str)) else: self.fail('Multiple messages contained text "%s": %s' % (text, ", ".join(('"%s"' % m) for m in matches))) def assert_message_not_contains(self, response, text): """ Assert that no message contains the given text. """ messages = response.context['messages'] matches = [m for m in messages if text in m.message] if len(matches) > 0: self.fail('Message(s) contained text "%s": %s' % (text, ", ".join(('"%s"' % m) for m in matches))) 

从Django文档 :

在模板之外,可以使用get_messages()

所以,你可以写一些像:

 from django.contrib.messages import get_messages [...] messages = [m.message for m in get_messages(response.wsgi_request)] self.assertIn('My message', messages) 

僵局之一的简单版本:

 class TestCaseMessagesMixture(object): def assertMessageCount(self, response, expect_num): """ Asserts that exactly the given number of messages have been sent. """ actual_num = len(response.context['messages']) if actual_num != expect_num: self.fail('Message count was %d, expected %d' % (actual_num, expect_num) ) def assertMessageEqual(self, response, text): """ Asserts that the response includes the message text. """ messages = [m.message for m in response.context['messages']] if text not in messages: self.fail( 'No message with text "%s", messages were: %s' % (text, messages) ) def assertMessageNotEqual(self, response, text): """ Asserts that the response does not include the message text. """ messages = [m.message for m in response.context['messages']] if text in messages: self.fail( 'Message with text "%s" found, messages were: %s' % (text, messages) )