Reputation: 34630
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
Upvotes: 73
Views: 37035
Reputation: 50786
The attribute is_authenticated
on the User
instance is always True
. It is False
for request.user.is_authenticated
in the case that request.user
is an instance of AnonymousUser
, whose attribute is_authenticated
is always 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
).
Upvotes: 10
Reputation: 70673
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
Upvotes: 114
Reputation: 777
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.
Upvotes: 2
Reputation: 2746
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.
Upvotes: 85
Reputation: 5663
Django's TestClient has a login method which returns True if the user was successfully logged in.
Upvotes: 11
Reputation: 46264
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.
Upvotes: 2