Afzal S.H.
Afzal S.H.

Reputation: 1084

Django Test Client does not create a user object but creates a anonymous user object

I have implemented user registration for my project and I am indeed able to find the object created using User.objects.get() from the Django shell client.

But when running tests it seems that an AnonymousUser object is created instead of a User object.

I have the following code;

forms.py;

from django import forms
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm

class UserCreateForm(UserCreationForm):
    """
    Extends Django's UserCreationForm
    """
    email_exists_message = "A user with that email id already exists."
    email = forms.EmailField(required=True)
    first_name = forms.CharField(required=True)
    last_name = forms.CharField()

    class Meta:
        model = User
        fields = ("first_name", "last_name", "username", "email", "password1", "password2")

    def clean_email(self):
        email = self.cleaned_data["email"]
        try: 
            User._default_manager.get(email=email)
        except User.DoesNotExist:
            return email
        raise forms.ValidationError(
            self.email_exists_message,
            code='duplicate_email',
        )

    def save(self, commit=True):
        user = super(UserCreateForm, self).save(commit=False)
        user.email = self.cleaned_data["email"]
        user.first_name = self.cleaned_data["first_name"]
        user.last_name = self.cleaned_data["last_name"]
        if commit:
            user.save()
        return user

urls.py;

.
.
.
from stationrunner.forms import UserCreateForm
.
.

urlpatterns = patterns('',
    url('^registration/', 
        CreateView.as_view(template_name='auth/register.html',
                       form_class=UserCreateForm,
                       success_url='/stations/create'
        ),
        name='userregistration'
    ),
    .
    .
    .
)

and finally my tests.py;

from django.test import TestCase
from django.core.urlresolvers import reverse
from django.contrib.auth.models import User

class TestUserSignUp(TestCase):
    .
    .
    .
    def test_submission_form_creates_user_object(self):
    """
    Tests if submission of the form on page for creation of a 
    user creates a user object and its attributes take the 
    expected values
    """
    first_name = "somename"
    last_name = "somename"
    email = "[email protected]"
    username = "someusername"
    password = "somepassword"
    response = self.client.post(reverse("userregistration"),
                                {"first_name": first_name,
                                 "last_name": last_name,
                                 "email": email,
                                 "username": username,
                                 "password": password},
                                follow=True)
    assert "user" in response.context
    user = response.context["user"]
    assert user.first_name == first_name
    assert user.last_name == last_name
    assert user.email == email
    assert user.username == username
    assert user.password == user.set_password(password)

As said above a user object is indeed getting saved into db and I further assured it using userobject.is_authenticated() from the django shell

But when I run my test I get the following failure

>       assert user.first_name == first_name

stationrunner/tests.py:145: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _      _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

self = <SimpleLazyObject: <django.contrib.auth.models.AnonymousUser     object at 0x7f815ac211d0>>, args = ('first_name',)

    def inner(self, *args):
        if self._wrapped is empty:
            self._setup()
>       return func(self._wrapped, *args)
E       AttributeError: 'AnonymousUser' object has no attribute 'first_name'

I am a newbie to Python/Django and I badly look forward for someone to explain to me what is happening here

Afzal

Update;

I imported authenticate and login to my forms.py and changed the save() method to look like;

def save(self, commit=True):
    user = super(UserCreateForm, self).save(commit=False)
    user.email = self.cleaned_data["email"]
    user.first_name = self.cleaned_data["first_name"]
    user.last_name = self.cleaned_data["last_name"]
    if commit:
        user.save()
        authenticate(username=user.username, password=user.password)
        log_user_in(user)
    return user

and added the expected log_user_in() method as;

def log_user_in(self, user):
    login(self.request, user)

I have tried to log the user in and hence expects my response.context to contain not a anonymous user object but a user object itself.

But the code doesn't work it seems. I still get the same error. As already said I'm a newbie so please forgive if there is any silliness.

Upvotes: 0

Views: 543

Answers (1)

Daniel Hepper
Daniel Hepper

Reputation: 29957

You are creating a new user, but you are not authenticating as that user. Therefor, the user you read from response.context is the AnonymousUser.

If you actually want to log in the user upon creation, the best way is probably to create your own form view.

Otherwise you have to change your test to read the newly created user from the database.

Upvotes: 1

Related Questions