Django Test Case Error 'WSGIRequest' object has no attribute 'session'
Asked Answered
P

3

8

I'm trying to write some tests for my django app and it's throwing up an error:

File "/Users/croberts/.virtualenvs/litem/lib/python3.4/site-packages/django/contrib/auth/__init__.py", line 101, in login
    if SESSION_KEY in request.session:
AttributeError: 'WSGIRequest' object has no attribute 'session'

Here's my code that I am trying to run:

class SimpleTest(TestCase):
    def setUp(self):
        self.request_factory = RequestFactory()

    def test_signup(self):
        request = self.request_factory.post("/signup/", {
            "email": "[email protected]", 
            "password": "password", 
            "password-confirm": "password", 
            "firm": "big law firm"})
        response = signup_user(request)
        user = User.objects.get(email="[email protected]")
        self.assertEqual(user.username, "[email protected]")
        self.assertEqual(user.firm, "big law firm")
        self.assertEqual(response.status_code, 302) #if it's successful it redirects.

Here's my middleware's:

MIDDLEWARE_CLASSES = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

and my installed apps:

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'patents',
]
Peridotite answered 26/2, 2016 at 19:2 Comment(1)
I just updated the question. It's set in the setUp method.Peridotite
M
12

Try using the test client instead of the request factory. This has the advantage of testing your URL config as well.

class SimpleTest(TestCase):
    def test_signup(self):
        response = self.client.post("/signup/", {
            "email": "[email protected]", 
            "password": "password", 
            "password-confirm": "password", 
            "firm": "big law firm"})
        user = User.objects.get(email="[email protected]")
        self.assertEqual(user.username, "[email protected]")
        self.assertEqual(user.firm, "big law firm")
        self.assertEqual(response.status_code, 302) #if it's successful it redirects.
Mord answered 26/2, 2016 at 21:8 Comment(2)
A useful tidbit, if you're experiencing this issue because you require a user to be logged in, try taking advantage of Client's login() method. It's as simple as my_client.login(username='my_username', password='my_password')Weidman
"This has the advantage of testing your URL config as well." This is a disadvantage if we're writing unit tests.Elisavetpol
A
10

For anyone using Django 2.0 and up - the RequestFactory() doesn't have access to the Middleware:

It does not support middleware. Session and authentication attributes must be supplied by the test itself if required for the view to function properly.

https://docs.djangoproject.com/en/2.2/topics/testing/advanced/#the-request-factory

Therefore, it needs to be added manually as follows:

from django.contrib.sessions.middleware import SessionMiddleware

class SimpleTest(TestCase):
    def setUp(self):
        self.request_factory = RequestFactory()

        middleware = SessionMiddleware()
        middleware.process_request(self.request_factory)
        self.request_factory.session.save()

    def test_signup(self):
        ...
Artois answered 2/6, 2020 at 7:57 Comment(1)
what's the question?Kussell
D
8

In django 3.1, I got this error 'AttributeError: 'RequestFactory' object has no attribute 'COOKIES' after following @Alasdair's answer. I solved this by initializing the request first, below is the snippet.

def setUp(self):
    request = RequestFactory().get('/')
    middleware = SessionMiddleware()
    middleware.process_request(request)
    request.session.save()

Edit for version 4.0 the sessionmiddlewre requires a positional argument: 'get_response' so:

def setUp(self):
    request = RequestFactory().get('/')
    middleware = SessionMiddleware(request)
    middleware.process_request(request)
    request.session.save()
    

Distraint answered 26/11, 2020 at 8:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.