3

In Django, I have a view, which will redirect to the register page for certain users and I would like to write a test for this.

The standard request.client.get used for testing doesn't allow me to specify a user (it just defaults to anonymous_user?), so I can't test the behaviour.

With RequestFactory() I was able to specify request.user. However, it is not following the redirect and the test fails.

from .views import my_view
from django.test import RequestFactory()

def test_mytest(self):
    user = create_guest_user()
    self.factory = RequestFactory()
    request = self.factory.get(reverse('my_view'), follow=True)
    request.user = user
    response = my_view(request)
    self.assertContains(response, "page where redirected should contain this")

It fails on the last line with this error message:

AssertionError: 302 != 200 : Couldn't retrieve content: Response code was 302 (expected 200)

Any ideas how to do this?

EDIT: As far as I can tell this is not a duplicate as it refers to RequestFactory(), which is different from self.client.get (where follow=True will solve the problem).

M3RS
  • 4,254
  • 1
  • 24
  • 40
  • 1
    Possible duplicate of [Django : Testing if the page has redirected to the desired url](https://stackoverflow.com/questions/14951356/django-testing-if-the-page-has-redirected-to-the-desired-url) – Henrik Andersson Nov 20 '17 at 12:15
  • It is not a duplicate. In that case the focus was `SimpleTestCase` over here we are talking the `RequestFactory` class. It is also about following a redirect not `assertRedirect` – stephen Nov 20 '17 at 12:39
  • 1
    You can't make `RequestFactory()` follow requests. It simply creates a `request` object. If you use `RequestFactory` then you'll need to check the response code, get the redirect location, resolve that location to a view, then call that view. The `client` is designed to take care of all of that for you, so you should use it instead. – Alasdair Nov 20 '17 at 12:57
  • Thanks Alasdair - that helped a lot together with the recommendation below to login the anonymous user. – M3RS Nov 20 '17 at 13:05

1 Answers1

6

To authenticate the default Django client, you can use the force_login method on your client:

user = create_guest_user()
self.client.force_login(user)

If your site uses Django’s authentication system, you can use the force_login() method to simulate the effect of a user logging into the site. Use this method instead of login() when a test requires a user be logged in and the details of how a user logged in aren’t important.

To follow the redirection (or not) using the test client, you must use the follow argument, as described here: https://docs.djangoproject.com/en/1.11/topics/testing/tools/#django.test.Client.get

self.client.get(url, follow=True)

If you set follow to True the client will follow any redirects and a redirect_chain attribute will be set in the response object containing tuples of the intermediate urls and status codes.

So your full code should look like this:

from django.test import TestCase

class MyTestCase(TestCase):
    def test_mytest(self):
        user = create_guest_user()
        self.client.force_login(user)
        response = self.client.get(reverse('my_view'), follow=True)
        # Do your assertions on the response here
Clément Denoix
  • 1,396
  • 8
  • 17
  • 2
    This answer doesn't deserve the downvote. If the OP wants to follow redirects, then they should use the `client` instead of `RequestFactory()`. This answer shows how to avoid the anonymous user problem when using the client. – Alasdair Nov 20 '17 at 12:58