6

I am using RequestFactory in a Django test, and I can't find the right way to access the session variable, and I'm getting the following error when I try self.factory._session["zip_id"] or self.factory.session["zip_id"].

======================================================================
ERROR: test_middleware (dj_geo.tests.IPToZipMiddleWareTest)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "c:\dj_site_test\dj_geo\tests.py", line 36, in test_middleware
    assert self.factory._session["zip_id"] != None
AttributeError: 'RequestFactory' object has no attribute '_session'

----------------------------------------------------------------------



@override_settings(MIDDLEWARE_CLASSES=(
    'dj_geo.middleware.IPToZipMiddleWare'
))
class IPToZipMiddleWareTest(TestCase):

    def test_middleware(self):
        Zipcode.syncdb()
        assert Zipcode.objects.all().count() > 0

        self.factory = RequestFactory()
        self.request = self.factory.get('/', {}, **{'REMOTE_ADDR':'108.31.178.99'})
        assert self.factory._session["zip_id"] != None
        assert self.factory._session["zip_id"] != ""
Sardorbek Imomaliev
  • 14,861
  • 2
  • 51
  • 63
user1187968
  • 7,154
  • 16
  • 81
  • 152

4 Answers4

12

Save session information to request using your middleware:

from django.contrib.sessions.middleware import SessionMiddleware

request = RequestFactory().get('/')
middleware = SessionMiddleware()
middleware.process_request(request)
request.session.save()
Ronan Boiteau
  • 9,608
  • 6
  • 34
  • 56
Manish S
  • 801
  • 11
  • 12
  • 4
    I started getting `TypeError: __init__() missing 1 required positional argument: 'get_response'` on Django 4.0 with this solution. I solved it by `middleware = SessionMiddleware(lambda x: x)` Although I don't know, if it is really correct solution. – Petr Dlouhý Jan 14 '22 at 08:51
6

You can use SessionMiddleware, indeed. However, its constructor requires a callback, as any middleware. The callback is provided by Django run-time in order to keep processing the middleware chain or to execute the view as soon as the chain reaches the end. Since we are not interested in view execution, for this case, you may do the following:

from django.contrib.sessions.middleware import SessionMiddleware

request = RequestFactory().get('/')
middleware = SessionMiddleware(lambda x: None)
middleware.process_request(request)
request.session.save()

By processing the request, session field will be added to it and you can keep going with your testing.

0

You may need to use the SessionMiddleware to process your request, then save it to store the session. You can refer to this article. I also don't think it's a good idea to access the protected attributes of the factory directly, like this self.factory._session["zip_id"], it will just get you into more problems. Goodluck!

-1

You need to use Client for this instead of RequestFactory

self.factory = Client()
Sardorbek Imomaliev
  • 14,861
  • 2
  • 51
  • 63