Felix D.
Felix D.

Reputation: 2220

Test not passing in Django when it should

I just started with Django and thought maybe someone could enlighten me about a simple test I wrote that should pass but obviously doesn't. Well, I say it should but being pretty new to Django I guess my lack of knowledge is the reason it fails.

I extended the django User model with another model and a one to one relationship, as suggested in the docs, to add a field to the model. That model, namely UserStep, simply contains an Integer that starts at zero. I decided to extend the manager too to implement a method named setUserStep that set the step to a new value if the condition is met.

models.py

class UserStepManager(models.Manager):
    def setUserStep(self, user, conditional_step, step):
        if user.userstep.step == conditional_step:
            user.userstep.step = step
            user.userstep.save()


class UserStep(models.Model):
    """This model holds the user step count"""
    user = models.OneToOneField(User)
    step = models.IntegerField(default=0)
    # we set the custom manager
    objects = UserStepManager()

Then when the User signs up, a new UserStep object gets created.

models.py

@receiver(user_signed_up)
def complete_social_signup(sender, **kwargs):
    """We start step to 0"""
    user = kwargs.pop('user')
    us = UserStep(user=user)
    us.save()

I use the method setUserStep defined in the manager in one of my views that gets called when a user requests /phase1/step1/ URL. So, if the current step is zero, set it to 1. As simple as that.

views.py

@login_required
def step1(request):
    context_dict = {}
    UserStep.objects.setUserStep(request.user, 0, 1)
    return render(request, 'phase1/step1.html', context_dict)

I tested that behavior by hand by signing up and calling that view, and everything worked as expected. When I check the database, user.userstep.step is set to 1.

Then, being a good boy, I decided I would start writing some tests (I'm not at the point where I write the tests first yet, I should write tests to test my tests before that :P).

tests.py

class MyTests(TestCase):

    def setUp(self):
        self.test_user = User.objects.create_user(username="test",
                                                  email="test@test.com",
                                                  password="test")
        # Mock user_signed_up signal.
        us = UserStep(user=self.test_user)
        us.save()
        self.c = Client()

    def test_step_gets_incremented(self):
        self.c.login(username="test", password="test")
        response = self.c.get('/phase1/step1/')
        # user is logged in, the test should pass
        self.assertEqual(response.status_code, 200)
        current_user_step = self.test_user.userstep.step
        # Test doesn't pass. WHY ME
        self.assertEqual(current_user_step, 1)

AND BOOM AssertionError: 0 != 1

I'm even doing a simple print in my view method and it gets called as it should.

Thanks!

Upvotes: 3

Views: 73

Answers (1)

JuniorCompressor
JuniorCompressor

Reputation: 20025

You have to reload test_user from the database since changing of the user is performed to another user instance. That means if:

u1 = User.objects.get(id = 1)
u2 = User.objects.get(id = 1)

changes to u1 (even if saved) are not mirrored to u2. So you have to get again the user from the db after the request.

Upvotes: 4

Related Questions