template - Pruebas de Django: compruebe los mensajes para una vista que redirige
views django example (5)
He estado escribiendo pruebas para una de mis aplicaciones de django y he estado buscando solucionar este problema desde hace bastante tiempo. Tengo una vista que envía mensajes usando django.contrib.messages
para diferentes casos. La vista se parece a la siguiente.
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)
Ahora, mientras se prueba esta vista, la respuesta de client.get
no contiene el diccionario de context
que contiene los messages
ya que esta vista utiliza una redirección. Para las vistas que representan plantillas, podemos obtener acceso a la lista de messages = response.context.get(''messages'')
utilizando messages = response.context.get(''messages'')
. ¿Cómo podemos obtener messages
acceso para una vista que redirige?
Método alternativo de mensajes de burla (no es necesario seguir la redirección):
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...
Puede usar get_messages () con response.wsgi_request como este (probado en 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")
Si sus vistas están redireccionando y usa follow=true
en su solicitud al cliente de prueba, lo anterior no funcionará. Terminé escribiendo una función de ayuda para recibir el primer mensaje (y, en mi caso, solo) enviado con la respuesta.
@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
Incluyes esto dentro de tu clase de prueba y lo usas así:
message = self.getmessage(response)
Donde la response
es lo que obtienes de una get
o post
en un Client
.
Esto es un poco frágil pero con suerte le ahorra a alguien más tiempo.
Tuve el mismo problema al usar una aplicación de terceros.
Si desea obtener los mensajes de una vista que devuelve un HttpResponseRedict (desde el cual no puede acceder al contexto) desde otra vista, puede usar get_messages(request)
from django.contrib.messages import get_messages
storage = get_messages(request)
for message in storage:
do_something_with_the_message(message)
Sin embargo, esto borra el almacenamiento de mensajes, por lo que si desea acceder a los mensajes desde una plantilla más adelante, agregue:
storage.used = False
Use la opción follow=True
en la llamada client.get()
, y el cliente seguirá la redirección. Luego puede probar que el mensaje se encuentra en el contexto de la vista a la que redirigió.
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)