Django login tests session problems

501 Views Asked by At

Here are the two lines of code I'm trying to cover with tests:

from django.contrib.auth import login
from django.views.generic.edit import FormView

from accounts.forms import UsernameLoginForm


class LoginView(FormView):
    form_class = UsernameLoginForm
    success_url = '/'
    template_name = 'login.html'

    def form_valid(self, form):
        login(self.request, form.get_user())
        return super(LoginView, self).form_valid(form)

This seems to be the proper way to functionally implement a login form extended from django.contrib.auth.forms.AuthenticationForm, but I had to dig the code out of the admin login view myself so it needs decent testing.

I'm having problems getting the test environment to set the user on the session. RequestFactory has no session support so this is what I tried:

from django.contrib.auth.models import User
from django.test import TestCase
from django.test.client import RequestFactory
import mox

from accounts.forms import UsernameLoginForm
from accounts.views import LoginView


class ViewTests(TestCase):

    def test_login(self):
        user = User.objects.create(username='userfoo')
        view = LoginView()
#        request = RequestFactory()
        view.request = self.client

        self.moxx = mox.Mox()
        form = self.moxx.CreateMock(UsernameLoginForm)
        form.get_user().AndReturn(user)

        self.moxx.ReplayAll()
        view.form_valid(form)
        self.moxx.VerifyAll()

        self.assertTrue(request.user)

And this is the error that causes:

  File "/home/renoc/.virtualenvs/alc/local/lib/python2.7/site-packages/django/contrib/auth/__init__.py", line 110, in login
    request.session.cycle_key()
  File "/home/renoc/.virtualenvs/alc/local/lib/python2.7/site-packages/django/contrib/sessions/backends/base.py", line 283, in cycle_key
    data = self._session_cache
AttributeError: 'SessionStore' object has no attribute '_session_cache'

self.client.request.session is volatile and if I try to set an attribute on it it throws no errors but it doesn't have the attribute when accessed either.

1

There are 1 best solutions below

0
On BEST ANSWER

After a lot of work I found that I could attach the session generated by TestCase.client to the RequestFactory and have an instance I could alter. Here is what I came up with to make my tests work.

from django.contrib.auth.models import User
from django.test import TestCase
from django.test.client import RequestFactory
import mox

from accounts.forms import UsernameLoginForm
from accounts.views import LoginView


class ViewTests(TestCase):

    def setUp(self):
        self.moxx = mox.Mox()

    def tearDown(self):
        self.moxx.UnsetStubs()

    def test_login(self):
        user = User.objects.create(username='userfoo')
        user.backend = ''
        view = LoginView()
        request = RequestFactory()
        request.META = {}
        request.user = None
        request.session = self.client.session
        request.session.create()
        view.request = request

        form = self.moxx.CreateMock(UsernameLoginForm)
        form.get_user().AndReturn(user)

        self.moxx.ReplayAll()
        view.form_valid(form)
        self.moxx.VerifyAll()

        self.assertTrue(request.user)

I hope you will still offer suggestions including why I shouldn't be doing anything like this in the first place.