Django Testing-проверка сообщений для представления, которое перенаправляет
я писал тесты для одного из моих приложений django и искал, чтобы обойти эту проблему в течение довольно долгого времени. У меня есть представление, которое отправляет сообщения с помощью django.contrib.messages
для различных случаев. Вид выглядит примерно так.
from django.contrib import messages
from django.shortcuts import redirect
import custom_messages
def some_view(request):
""" This is a sample view for testing purposes.
"""
some_condition = models.SomeModel.objects.get_or_none(
condition=some_condition)
if some_condition:
messages.success(request, custom_message.SUCCESS)
else:
messages.error(request, custom_message.ERROR)
redirect(some_other_view)
теперь, при тестировании этого представления client.get
's ответ не содержит context
словарь, содержащий messages
поскольку это представление использует перенаправление. Для представлений, отображающих шаблоны, мы можем получить доступ к список сообщений с помощью messages = response.context.get('messages')
. Как мы можем получить доступ messages
для представления, которое перенаправляет?
5 ответов
использовать на client.get()
вызов, и клиент будет следовать перенаправлению. Затем можно проверить, что сообщение находится в контексте перенаправленного представления.
def test_some_view(self):
# use follow=True to follow redirect
response = self.client.get('/some-url/', follow=True)
# don't really need to check status code because assertRedirects will check it
self.assertEqual(response.status_code, 200)
self.assertRedirects(response, '/some-other-url/')
# get message from context and check that expected text is there
message = list(response.context.get('messages'))[0]
self.assertEqual(message.tags, "success")
self.assertTrue("success text" in message.message)
вы можете использовать get_messages() с Ответ.wsgi_request как это (протестировано в Django 1.10):
from django.contrib.messages import get_messages
...
def test_view(self):
response = self.client.get('/some-url/') # you don't need follow=True
self.assertRedirects(response, '/some-other-url/')
# each element is an instance of django.contrib.messages.storage.base.Message
all_messages = [msg for msg in get_messages(response.wsgi_request)]
# here's how you test the first message
self.assertEqual(all_messages[0].tags, "success")
self.assertEqual(all_messages[0].message, "you have done well")
если ваши представления перенаправляются и вы используете follow=true
в вашем запросе тестовому клиенту вышеизложенное не работает. В итоге я написал вспомогательную функцию, чтобы получить первое (и в моем случае только) сообщение, отправленное с ответом.
@classmethod
def getmessage(cls, response):
"""Helper method to return message from response """
for c in response.context:
message = [m for m in c.get('messages')][0]
if message:
return message
вы включаете это в свой тестовый класс и используете его следующим образом:
message = self.getmessage(response)
здесь response
что вы получаете от get
или post
до Client
.
это немного хрупкой, но, надеюсь, это спасет кого-то еще как-нибудь.
у меня была такая же проблема при использовании стороннего приложения.
Если вы хотите получить сообщения из представления, которое возвращает HttpResponseRedict (из которого вы не можете получить доступ к контексту) из другого представления, вы можете использовать get_messages(request)
from django.contrib.messages import get_messages
storage = get_messages(request)
for message in storage:
do_something_with_the_message(message)
это очищает хранилище сообщений, поэтому, если вы хотите получить доступ к сообщениям из шаблона позже, добавьте:
storage.used = False
альтернативный метод насмешливых сообщений (не нужно следовать перенаправлению):
from mock import ANY, patch
from django.contrib import messages
@patch('myapp.views.messages.add_message')
def test_some_view(self, mock_add_message):
r = self.client.get('/some-url/')
mock_add_message.assert_called_once_with(ANY, messages.ERROR, 'Expected message.') # or assert_called_with, assert_has_calls...