如何对“新风格”Django中间件进行单元测试

3

我正在学习如何对Django中间件进行单元测试。

在“旧风格”的中间件中,使用process_request()加载中间件以测试结果非常容易。例如:

def test_session(self):
    request = self.factory.get('/')
    session_middleware = SessionMiddleware()
    session_middleware.process_request(request)
    // Do stuff

然而,在“新风格”中,这种情况不存在。例如,我该如何测试以下示例提供的Django文档
class TimezoneMiddleware:
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        tzname = request.session.get('django_timezone')
        if tzname:
            timezone.activate(pytz.timezone(tzname))
        else:
            timezone.deactivate()
        return self.get_response(request)

使用 TimezoneMiddleware(request) 会调用__init__但不会调用__call__吗?
1个回答

9
正如您所看到的,中间件只是实现了一个__call__魔法方法。这意味着该类的实例是可调用的。
旧版和新版中间件之间的区别在于,新版中间件只是返回一个可调用对象的可调用对象 - 首先使用get_response回调函数调用它,然后再使用实际请求调用返回的可调用对象。get_response是由Django自己提供/注入的可调用对象,它是一个用于返回视图响应或链中下一个中间件的函数。
因此,为了测试您的SessionMiddleware,您可以执行以下操作:
import mock

def test_middleware(self):
    get_response = mock.MagicMock()
    request = self.factory.get('/')

    middleware = SessionMiddleware(get_response)
    response = middleware(request)

    # ensure get_response has been returned 
    # (or not, if your middleware does something else)
    self.assertEqual(get_response.return_value, response)
    

谢谢,这个返回response = middleware(request)时出现了AttributeError: 'WSGIRequest' object has no attribute 'session'的错误? - alias51
1
你正在测试哪个中间件?因为SessionMiddleware是将会话对象附加到请求上的中间件:https://github.com/django/django/blob/master/django/contrib/sessions/middleware.py#L24 - 如果你正在测试依赖于会话中间件的其他中间件,你要么先使用会话中间件,要么在请求上模拟.session属性。 - samu
我正在测试问题中展示的TimezoneMiddleware,它需要一个会话。 - alias51
1
是的,你可以在这一行中看到:tzname = request.session.get('django_timezone') - 这需要先将一个会话附加到请求上。 - samu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接