I am learning how to unittest Django middleware.
In the 'old style' Middleware, it was easy enough to load middleware using process_request()
to test results. E.g.
def test_session(self):
request = self.factory.get('/')
session_middleware = SessionMiddleware()
session_middleware.process_request(request)
// Do stuff
However, in the 'new style' this does not exist. For example, how would I test the following example Django docs provide?
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)
Using TimezoneMiddleware(request)
will call the __init__
but not the __call__
?
As you can see, the middleware simply implements a __call__
magic method. This means the instance of this class is callable.
The difference between the old-style and new-style middleware is that the new middleware is simply a callable that returns a callable - first you call it with a get_response
callback, and then you call the returned callable with the actual request. get_response
is a callable provided/injected by Django itself, and it's a function used to either return the view response, or the next middleware in the chain.
So, in order to test your SessionMiddleware
, you could do the following:
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)