Test that user was logged in successfully

Django

Django Problem Overview


How can I test that a user is logged in after submitting the registration form?

I tried the following but it returns True even before I added the login logic to my registration view.

def test_that_user_gets_logged_in(self):
    response = self.client.post(reverse('auth-registration'), 
                                { 'username':'foo', 
                                  'password1':'bar', 
                                  'password2':'bar' } )

    user = User.objects.get(username='foo')
    assert user.is_authenticated()

The code that's being tested:

class RegistrationView(CreateView):
    template_name = 'auth/registration.html'
    form_class = UserCreationForm
    success_url = '/'

    def auth_login(self, request, username, password):
        '''
        Authenticate always needs to be called before login because it
        adds which backend did the authentication which is required by login.
        '''

        user = authenticate(username=username, password=password)
        login(request, user)

    def form_valid(self, form):
        '''
        Overwrite form_valid to login.
        '''

        #save the user
        response = super(RegistrationView, self).form_valid(form)
        
        #Get the user creditials
        username = form.cleaned_data['username']
        password = form.cleaned_data['password1']

        #authenticate and login
        self.auth_login(self.request, username, password)

        return response

Django Solutions


Solution 1 - Django

You can use the get_user method of the auth module. It says it wants a request as parameter, but it only ever uses the session attribute of the request. And it just so happens that our Client has that attribute.

from django.contrib import auth
user = auth.get_user(self.client)
assert user.is_authenticated

Solution 2 - Django

> This is not the best answer. See https://stackoverflow.com/a/35871564/307511 > > Chronial has given > an excellent example on how to make this assertion below. His answer > better than mine for nowadays code.


The most straightforward method to test if a user is logged in is by testing the Client object:

self.assertIn('_auth_user_id', self.client.session)

You could also check if a specific user is logged in:

self.assertEqual(int(self.client.session['_auth_user_id']), user.pk)

As an additional info, the response.request object is not a HttpRequest object; instead, it's an ordinary dict with some info about the actual request, so it won't have the user attribute anyway.

Also, testing the response.context object is not safe because you don't aways have a context.

Solution 3 - Django

Django's TestClient has a login method which returns True if the user was successfully logged in.

Solution 4 - Django

The method is_authenticated() on the User model always returns True. False is returned for request.user.is_authenticated() in the case that request.user is an instance of AnonymousUser, which is_authenticated() method always returns False. While testing you can have a look at response.context['request'].user.is_authenticated().

You can also try to access another page in test which requires to be logged in, and see if response.status returns 200 or 302 (redirect from login_required).

Solution 5 - Django

Where are you initialising your self.client? What else is in your setUp method? I have a similar test and your code should work fine. Here's how I do it:

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


class UserTestCase(TestCase):

    def setUp(self):
        self.client = Client()

    def testLogin(self):
        print User.objects.all() # returns []
        response = self.client.post(reverse('auth-registration'), 
                            { 'username':'foo', 
                              'password1':'bar', 
                              'password2':'bar' } )
        print User.objects.all() # returns one user
        print User.objects.all()[0].is_authenticated() # returns True

EDIT

If I comment out my login logic, I don't get any User after self.client.post(. If you really want to check if the user has been authenticated, use the self.client to access another url which requires user authentication. Continuing from the above, access another page:

response = self.client.get(reverse('another-page-which-requires-authentication'))
print response.status_code

The above should return 200 to confirm that the user has authenticated. Anything else, it will redirect to the login page with a 302 code.

Solution 6 - Django

There is another succinct way, using wsgi_request in response:

response = self.client.post('/signup', data)
assert response.wsgi_request.user.is_authenticated()

and @Chronial 's manner is also available with wsgi_request:

from django.contrib import auth
user = auth.get_user(response.wsgi_request)
assert user.is_authenticated()

Because response.wsgi_request object has a session attribute.

However, I think using response.wsgi_request.user is more simple.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionPickelsView Question on Stackoverflow
Solution 1 - DjangoChronialView Answer on Stackoverflow
Solution 2 - DjangoemyllerView Answer on Stackoverflow
Solution 3 - DjangoJonatan LittkeView Answer on Stackoverflow
Solution 4 - DjangoBernhard VallantView Answer on Stackoverflow
Solution 5 - DjangoThierry LamView Answer on Stackoverflow
Solution 6 - DjangoAnyany PanView Answer on Stackoverflow