0

I have a Django app that uses the builtin login system.

I'm trying to write a unit test that verifies that the login url redirects to home if the user is already authenticated. Meaning, if an already authenticated user tries to visit the login url, they get redirected to home.

This is a built-in feature of Django's LoginView, and I have verified that it is indeed working. However, I'm not sure how to write a unit test for this.

Question: How do I verify that this redirect occurs via unit tests? LoginView returns a TemplateResponse, which doesn't have a url parameter.

What I have so far is this:

from django.test import TestCase
from django.urls import reverse

home  = reverse('home')
login = reverse('login')
logout = reverse('logout')
signup = reverse('signup')

USER_CREDS = { some users credentials }

class TestLoginView(TestCase):
    def test_login_redirect(self):
        self.client.post(signup, USER_CREDS)
        self.client.get(logout)
        self.client.post(login, USER_CREDS)
        response = self.client.get(login)
        self.assertRedirects(response, home)

EDIT: SimpleTestCase.assertRedirects does not work for TemplateResponse objects.

TemplateResponse objects do not contain a url parameter, which is required for SimpleTestCase.assertRedirect.

The method raises the following error: AttributeError: 'TemplateResponse' object has no attribute 'url'

This is not the same as the linked question, because the response object from a LoginView is a TemplateResponse, not an HttpResponse.

touch my body
  • 1,272
  • 17
  • 31
  • Possible duplicate of [Django : Testing if the page has redirected to the desired url](https://stackoverflow.com/q/14951356/1165509) – marcanuy Sep 14 '18 at 21:39
  • @marcanuy these are not the same, as explained in the edit. Thank you for trying to find a suitable answer though. – touch my body Sep 14 '18 at 21:54

1 Answers1

-2

You can check that the login process redirects to the desired named URL with assertRedirects:

SimpleTestCase.assertRedirects(response, expected_url, status_code=302, target_status_code=200, msg_prefix='', fetch_redirect_response=True)

Asserts that the response returned a status_code redirect status, redirected to expected_url (including any GET data), and that the final page was received with target_status_code.

Then in your test:

self.assertRedirects(response, home)

Edit

I've just had a similar problem, few notes:

Instead of performing the login process, you can use TestCase.force_login that skips the authentication and verification steps.

class TestLoginView(TestCase):
    def test_login_redirect(self):
        self.client.force_login(user)

        # logged user retrieves the login page
        response = self.client.get(login)

        self.assertRedirects(response, home)

Response should be a 302 redirect to home: <HttpResponseRedirect status_code=302, "text/html; charset=utf-8", url="/">

If you are not getting a redirect when doing response = self.client.get(login) that means that it is loading the login page, which is what you don't want, so you have to fix that error.

So the problem is not that TemplateResponse objects do not contain a url parameter, it is that your login page isn't redirecting a logged in user to the home page.

marcanuy
  • 19,934
  • 8
  • 56
  • 109
  • Thank you for your help. Are you sure this works? It's not working for me (saying status=200), and I've verified that the redirect is occurring via the console output (when I manually try to go to that url in the browser). – touch my body Sep 14 '18 at 20:46
  • @user4343502 I'm sure , I am using it. Capture the response when you do the post, not get, this is where your client logs in. – marcanuy Sep 14 '18 at 20:50
  • I'm testing to see if visiting the url `login` after logging in will redirect me away from the `login` page (I don't want users to visit the `login` page if they're already authenticated). I think you're referencing the redirect *after* the act of logging in. – touch my body Sep 14 '18 at 20:55
  • @user4343502 updated answer, it seems it was right after all 8) – marcanuy Sep 25 '18 at 12:58