我一直在写测试对于我的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
的响应不包含它context
包含字典messages
,因为这视图使用重定向。 对于渲染模板的观点,我们可以使用get访问消息列表messages = response.context.get('messages')
我们如何才能访问messages
为重定向一个看法?
使用follow=True
选项,在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)
您可以使用response.wsgi_request像这样(在Django 1.10测试)get_messages():
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...