How do I modify the session in the Django test framework
Asked Answered
S

5

39

My site allows individuals to contribute content in the absence of being logged in by creating a User based on the current session_key

I would like to setup a test for my view, but it seems that it is not possible to modify the request.session:

I'd like to do this:

from django.contrib.sessions.models import Session
s = Session()
s.expire_date = '2010-12-05'
s.session_key = 'my_session_key'
s.save()
self.client.session = s
response = self.client.get('/myview/')

But I get the error:

AttributeError: can't set attribute

Thoughts on how to modify the client session before making get requests? I have seen this and it doesn't seem to work

Stalagmite answered 15/12, 2010 at 19:1 Comment(1)
session is a dict-like object, you should use s[x] to get and set valuesMarvel
O
38

This is how I did it (inspired by a solution in http://blog.mediaonfire.com/?p=36).

from django.test import TestCase
from django.conf import settings
from django.utils.importlib import import_module

class SessionTestCase(TestCase):
    def setUp(self):
        # http://code.djangoproject.com/ticket/10899
        settings.SESSION_ENGINE = 'django.contrib.sessions.backends.file'
        engine = import_module(settings.SESSION_ENGINE)
        store = engine.SessionStore()
        store.save()
        self.session = store
        self.client.cookies[settings.SESSION_COOKIE_NAME] = store.session_key

After that, you may create your tests as:

class BlahTestCase(SessionTestCase):

    def test_blah_with_session(self):
        session = self.session
        session['operator'] = 'Jimmy'
        session.save()

etc...

Octave answered 11/10, 2011 at 7:8 Comment(1)
Does this still work with django 1.6 using the Pickle serializer (instead of the now standard JSONSerializer for SESSION_SERIALIZER)Deception
H
72

The client object of the django testing framework makes possible to touch the session. Look at http://docs.djangoproject.com/en/dev/topics/testing/?from=olddocs#django.test.client.Client.session for details

Be careful : To modify the session and then save it, it must be stored in a variable first (because a new SessionStore is created every time this property is accessed)

I think something like this below should work

s = self.client.session
s.update({
    "expire_date": '2010-12-05',
    "session_key": 'my_session_key',
})
s.save()
response = self.client.get('/myview/')
Huldahuldah answered 15/12, 2010 at 20:42 Comment(6)
Hi Luc, thanks for your help, but this doesn't work. I get the following error: AttributeError: 'dict' object has no attribute 'save' This occurs because the client.session object is a dictionary. It seems that client.session only becomes a true Session object after the request is made (and only if a user is logged in). Any other suggestions? You can repeat this by entering (from a shell): from django.test import Client client = Client() s = client.session s['expire_date']='2010-12-05' s['session_key']='my_session_key' s.save()Stalagmite
It looks like what luc suggested should work, but its a django bug: code.djangoproject.com/ticket/11475Lahr
plus 1 for Andrew - this bug is at least 4 years old it seems.Honebein
Regarding the first 2 comments, I believe the bug was fixed in the following commit.Ribband
This worked for me. Looks like the bug others commented about above is fixed.Gotcher
Saving session to a variable first fixed my issue.Val
O
38

This is how I did it (inspired by a solution in http://blog.mediaonfire.com/?p=36).

from django.test import TestCase
from django.conf import settings
from django.utils.importlib import import_module

class SessionTestCase(TestCase):
    def setUp(self):
        # http://code.djangoproject.com/ticket/10899
        settings.SESSION_ENGINE = 'django.contrib.sessions.backends.file'
        engine = import_module(settings.SESSION_ENGINE)
        store = engine.SessionStore()
        store.save()
        self.session = store
        self.client.cookies[settings.SESSION_COOKIE_NAME] = store.session_key

After that, you may create your tests as:

class BlahTestCase(SessionTestCase):

    def test_blah_with_session(self):
        session = self.session
        session['operator'] = 'Jimmy'
        session.save()

etc...

Octave answered 11/10, 2011 at 7:8 Comment(1)
Does this still work with django 1.6 using the Pickle serializer (instead of the now standard JSONSerializer for SESSION_SERIALIZER)Deception
B
15

As Andrew Austin already mentioned, it doesn't work because of this bug: https://code.djangoproject.com/ticket/11475

What you can do though is this:

from django.test import TestCase
from django.test.client import Client
from django.contrib.auth.models import User

class SessionTestCase(TestCase):
    def setUp(self):
        self.client = Client()
        User.objects.create_user('john', '[email protected]', 'johnpassword')
        self.client.login(username='john', password='johnpassword')

    def test_something_with_sessions(self):
        session = self.client.session
        session['key'] = 'value'
        session.save()

After creating and logging in a user with User.objects.create_user() and self.client.login(), as in the code above, sessions should work.

Blubbery answered 4/3, 2013 at 3:55 Comment(0)
P
4

as per the docs you can add values to the session in the test client via eg

def test_something(self):
    session = self.client.session
    session['somekey'] = 'test'
    session.save()

https://docs.djangoproject.com/en/dev/topics/testing/tools/#django.test.Client.session

This will let you test views that require data in the session to function correctly.

So for this question:

session = self.client.session
   session['expire_date'] = '2010-12-05'
   .....
   session.save()
Pneumatophore answered 7/12, 2017 at 19:14 Comment(0)
M
3

You can create a custom view which inserts dummy data such as the session.

The view with the corresponding url: /dummy/:

def dummy(request):
    # dummy init data
    request.session['expiry_date'] = '2010-12-05'
    return HttpResponse('Dummy data has been set successfully')

Than in test script just call self.client.get('/dummy/')

I also use this dummy view to initilize the dummy data in the session when testing by hand.

Madeup answered 16/4, 2011 at 13:51 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.