在单元测试期间如何在 Django RequestFactory 中设置消息传递和会话中间件

问题描述 投票:0回答:3

我有一个需要测试的函数,它以请求作为参数。它没有通过 URL 作为视图公开,因此我无法使用测试客户端对其进行测试。

我需要向其传递一个请求对象,并且请求对象需要启用消息中间件,因为函数中使用了消息中间件。

我正在使用 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)
python django unit-testing
3个回答
21
投票

这个问题被提出了,所以正如那里所说,您可以使用该代码修复您的单元测试:

from django.contrib.messages.storage.fallback import FallbackStorage
setattr(request, 'session', 'session')
messages = FallbackStorage(request)
setattr(request, '_messages', messages)

4
投票

如果您不需要测试请求对象本身的行为,您可以使用 mock 库而不是 RequestFactory 来模拟请求,例如:

import mock

request = mock.MagicMock()

# Call your function using the mocked request
store_to_request(request)

3
投票

与 Danag 的答案有效等效的方法是,在将请求对象传递给视图/函数之前,通过会话和消息中间件的 process_request 方法(按顺序)传递请求对象:

from django.contrib.sessions.middleware import SessionMiddleware
from django.contrib.messages.middleware import MessageMiddleware

request = request_factory.get("/")

sm = SessionMiddleware(lambda x: x)
sm.process_request(request)

mm = MessageMiddleware(lambda x: x)
mm.process_request(request)

或者为了方便起见,采用一种方法:

class MessageDependentTests(TestCase):
    
    request_factory = RequestFactory()
    session_middleware = SessionMiddleware(lambda x: x)
    message_middleware = MessageMiddleware(lambda x: x)
    
    def prepare_request(self, request):
        self.session_middleware.process_request(request)
        self.message_middleware.process_request(request)

    def test_something(self):
        request = self.request_factory.get('/')
        self.prepare_request(request)
        response = my_view(request)
        # test response below
© www.soinside.com 2019 - 2024. All rights reserved.