Как протестировать промежуточное ПО Django в новом стиле

Я изучаю, как тестировать промежуточное ПО Django.

В промежуточном ПО «старого стиля» было достаточно просто загрузить промежуточное ПО с помощью process_request() для проверки результатов. Например.

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

Однако в «новом стиле» этого нет. Например, как бы я протестировал следующий пример Django docs предоставить?

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__?


person alias51    schedule 16.07.2020    source источник


Ответы (1)


Как видите, промежуточное ПО просто реализует __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)
    
person samu    schedule 17.07.2020
comment
Спасибо, это возвращает response = middleware(request) с AttributeError: 'WSGIRequest' object has no attribute 'session' ? - person alias51; 17.07.2020
comment
Какое промежуточное ПО вы тестируете? Поскольку SessionMiddleware — это тот, который прикрепляет объект сеанса к запросу: github.com/django/django/blob/master/django/contrib/sessions/ — если вы тестируете другое промежуточное ПО, зависящее от промежуточного ПО сеанса, вы должны сначала использовать промежуточное ПО сеанса или издевайтесь над атрибутом .session в запросе. - person samu; 17.07.2020
comment
Я тестирую TimezoneMiddleware, показанный в вопросе, для которого требуется сеанс? - person alias51; 17.07.2020
comment
Да, вы можете увидеть это в этой строке: tzname = request.session.get('django_timezone') - требует, чтобы сессия была предварительно привязана к запросу. - person samu; 18.07.2020