如何在Django RequestFactory中设置消息和会话中间件以进行单元测试
我有一个需要测试的函数,它需要一个请求作为参数。这个函数没有通过网址暴露出来,所以我不能用测试客户端来测试它。
我需要把一个请求对象传给它,而且这个请求对象需要启用消息中间件,因为这个函数里用到了消息中间件。
我正在使用RequestFactory来创建我的请求。文档上说:
它不支持中间件。如果视图正常工作需要会话和认证属性,必须由测试本身提供。
我该如何用RequestFactory设置消息中间件呢?我想我还需要会话中间件才能让消息中间件正常工作。
这是我当前使用普通RequestFactory时测试产生的错误。
MessageFailure: You cannot add messages without installing django.contrib.messages.middleware.MessageMiddleware
这是我正在测试的函数,以便更好地理解这个问题:
from django.contrib import messages as django_messages
def store_to_request(self, request):
"""
Place all the messages stored in this class into message storage in
the request object supplied.
:param request: The request object to which we should store all the messages
:return: Does not return anything
"""
for message in self._messages:
django_messages.add_message(request, message.level, message.message, message.extra_tags,
message.fail_silently)
3 个回答
2
一种与Danag的回答效果相同的方法是,在将请求对象传递给视图或函数之前,先通过会话和消息中间件的process_request方法(按这个顺序)处理请求对象:
from django.contrib.sessions.middleware import SessionMiddleware
from django.contrib.messages.middleware import MessageMiddleware
request = request_factory.get()
sm = SessionMiddleware()
sm.process_request(request)
mm = MessageMiddleware()
mm.process_request(request)
为了方便,你可以把上面的操作放在一个方法里:
class MessageDependentTests(TestCase):
def setUp(self):
self.rf = RequestFactory()
self.sm = SessionMiddleware()
self.mm = MessageMiddleware()
return super().setUp()
def prepare_request(self, request):
self.sm.process_request(request)
self.mm.process_request(request)
def test_something(self):
request = self.rf.get('/')
self.prepare_request(request)
response = my_view(request)
# test response below
4
如果你不需要测试请求对象本身的行为,可以使用mock库来模拟请求,而不是使用RequestFactory。例如:
import mock
request = mock.MagicMock()
# Call your function using the mocked request
store_to_request(request)
22
这个问题在这里提到过 (点击查看),根据里面的说法,你可以用下面的代码来修复你的单元测试:
from django.contrib.messages.storage.fallback import FallbackStorage
setattr(request, 'session', 'session')
messages = FallbackStorage(request)
setattr(request, '_messages', messages)