简体   繁体   English

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

[英]How do I setup messaging and session middleware in a Django RequestFactory during unit testing

I have a function I need to test which takes a request as its argument.我有一个 function 我需要测试它以请求作为参数。 It is not exposed as a view by URL so I cannot test it with the test client.它没有作为 URL 的视图公开,因此我无法使用测试客户端对其进行测试。

I need to pass a request object to it, and the request object needs to have the messaging middleware enabled because messaging middleware is used in the function.我需要向它传递一个请求 object,而请求 object 需要启用消息中间件,因为消息中间件在 function 中使用。

I am using the RequestFactory to create my request.我正在使用 RequestFactory 来创建我的请求。 The documentation says: 文件说:

It does not support middleware.它不支持中间件。 Session and authentication attributes must be supplied by the test itself if required for the view to function properly.如果需要正确查看 function,则必须由测试本身提供 Session 和身份验证属性。

How do I setup the messaging middleware with the RequestFactory?如何使用 RequestFactory 设置消息传递中间件? I think I will also need the session middleware to make the messaging middleware work我想我还需要 session 中间件来使消息传递中间件工作

This is the error my test currently produces when using the vanilla RequestFactory.这是我的测试当前在使用 vanilla RequestFactory 时产生的错误。

MessageFailure: You cannot add messages without installing django.contrib.messages.middleware.MessageMiddleware

This is my function under test, in case it helps with understanding this problem:这是我正在测试的 function,以防它有助于理解这个问题:

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)

This issue was raised , so as there said, you can fix your unit tests using that code: 提出此问题,因此,您可以使用该代码修复单元测试:

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

If you don't need to test the behaviour of the request object itself you could mock the request using the mock library instead of RequestFactory eg: 如果您不需要测试请求对象本身的行为,您可以使用模拟库而不是RequestFactory来模拟请求,例如:

import mock

request = mock.MagicMock()

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

An effictively equivalent method to Danag's anwer would be to pass the request object through the process_request methods of the session and message middlewares (in that order) before passing it to the view/function: Danag 的 anwer 的有效等效方法是通过 session 的 process_request 方法和消息中间件(按此顺序)传递请求 object,然后再将其传递给视图/函数:

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)

You can do the above in a method for convenience:为方便起见,您可以在方法中执行上述操作:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM