Как я могу отправить сообщения unit test django?
В моем приложении django я пытаюсь написать unit test, который выполняет действие, а затем проверяет сообщения в ответе.
Насколько я могу судить, нет хорошего способа сделать это.
Я использую метод хранения 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
Ответы
Ответ 1
Я сделал эксперимент, чтобы проверить это. Я изменил параметр MESSAGE_STORAGE
в одном из моих проектов на 'django.contrib.messages.storage.cookie.CookieStorage'
и выполнил тест, который я написал для проверки сообщений. Это сработало.
Ключевым отличием от того, что вы делали, является способ получения сообщений. См. Ниже:
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])
Это может стоить попробовать.
Ответ 2
Я нашел очень простой подход:
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')
Резервное хранилище не поддерживает индексирование, но оно является итерируемым.
Ответ 3
Это работает для меня (отображает все сообщения):
print [m.message for m in list(response.context['messages'])]
Также есть несколько полезных методов, которые у меня есть в тестовом классе, унаследованном от Django TestCase. Если вы предпочитаете использовать их как функции, удалите аргументы self
и замените self.fail()
на raise
.
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)))
Ответ 4
Из документация 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)
Ответ 5
Упрощенная версия тупика:
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)
)