Using session object in Django unit test
Asked Answered
P

3

7

I am writing a login view and would like to add a unit test for the view. My view looks like this:

def login(request):

    if request.POST:
            usrname = request.POST.get('username')
            password = request.POST.get('password')
            user = authenticate(username=usrname, password=password)

            if user is not None:
                    auth_login(request, user)
                    return redirect('/core/home/')
            else:
                    context = {'error_message': "Invalid username or password"}
                    return render(request, 'core/login.html', context)
    else:
            c = {}
            c.update(csrf(request))
            return render_to_response('core/login.html',c)

def home(request):
    if request.user.is_authenticated():
        context = {'user' : request.user}
        return render(request, 'core/home.html', context)
    else:
        return render(request, 'core/login.html')

And my unit test looks like this:

class CoreViewTests(TestCase):
    def setUp(self):
            self.factory = RequestFactory()

    def test_login_view_with_valid_user(self):
            uf = UserFactory()
            user = uf.make_user("ValidUser1", "12345", "[email protected]")
            self.assertEqual(user.username, "ValidUser1")
            request = self.factory.post('/core/login', {"username": "ValidUser1", "password": "12345"})
            response = login(request)
            self.assertEqual(response.status_code, 200)

The unit test crash because they cannot find the session object. I follow couple tutorial on the websites by defining a dummy session dictionary but it doesn't help.

Can anyone shed some light for me how to write a unit test for a view that need to deal with session object?

Thanks.

Paquette answered 5/2, 2013 at 18:43 Comment(3)
Is this your exact code? You have an unclosed dictionary on this line request = self.factory.post('/core/login', {"username": "ValidUser1", "password": "12345") - it should be request = self.factory.post('/core/login', {"username": "ValidUser1", "password": "12345",})Baroscope
Yes it is, I copy my code from the repo. Probably I had a typo when I check in.Morceau
So do you still get the error with the code corrected?Baroscope
A
9

From the documentation for the RequestFactory object:

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

You could try manually setting request.session to be a dictionary with appropriate stuff in it, as you say. It might turn out to be easier to use the old-fashioned Django test client though.

Augustinaaugustine answered 5/2, 2013 at 19:50 Comment(0)
J
1

Such like this: request.session = {'num_visits': 0}

Johnsten answered 19/3, 2020 at 6:32 Comment(0)
S
0

In Django 3.2, using a dictionary did not work for me. I had to use the SessionMiddleware object to process the request and save a session, as shown here:

https://medium.com/@harshvb7/how-to-add-session-and-messages-in-django-requestfactory-16935a3351d0

from django.contrib.sessions.middleware import SessionMiddleware
from django.test import RequestFactory


class TestSomeView:
    
    def test_view(self):
        request = RequestFactory().get('/')
        
        # adding session
        middleware = SessionMiddleware()
        middleware.process_request(request)
        request.session.save()
Synchrocyclotron answered 7/9, 2023 at 16:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.