Django testing how to assert Redirect
Asked Answered
R

3

16

With the folliwing code I get this wrong result : nose.proxy.AssertionError: 302 != 200 : Couldn't retrieve redirection page '/mes_dossiers/': response code was 302 (expected 200)

what is wrong with my code ?

#test.py
from django.test import TestCase, RequestFactory, Client
from ..models import *
from ..views import *
from django.core.management import call_command

class Cas(TestCase):

    def setUp(self):
        call_command('loaddata', 'fixture_users.json', verbosity=1)
        call_command('loaddata', 'xxxxx_tests_xxxx.yaml', 
        verbosity=1)

    def test_dossier_duplicate(self) :
        request = self.factory.get('/dossier/3/copier/', follow = True)
        request.user = User.objects.get(id=3)
        pk = 3
        response = dossier_duplicate(request, pk)
        response.client = Client()
        self.assertRedirects(response,'/mes_dossiers/',status_code=302, 
        target_status_code=200)

#urls.py
urlpatterns = [    
url(r'^dossier/(?P<pk>[0-9]+)/copier/$',views.dossier_duplicate),  

]

#views.py
@login_required(login_url="/accounts/login/")
def dossier_duplicate(request, pk):

    dossier = get_object_or_404(Dossier, pk=pk)
    groupe = dossier.createdBy.groups.all()[0].name

    if not in_group(request.user, groupe) :
        return HttpResponseForbidden('Vous ne pouvez pas accéder à ce 
        dossier')

    else :

        #code to duplicate the "dossier" instance and child contents
        #
        #

        return redirect('/mes_dossiers/')
Rubadub answered 30/10, 2017 at 16:41 Comment(3)
What is the code you are testing? Also the title of the question seems to have nothing to do with the content of the question.Franciscka
Title edited. Sorry there was a mix between to post drafts.Bump
Could it be that the view at /mes_dossiers/ also redirects to another url?Franciscka
R
16

I've found more examples there:

Django : Testing if the page has redirected to the desired url

https://docs.djangoproject.com/en/3.0/topics/testing/tools/#django.test.SimpleTestCase.assertRedirects

and this worked:

class Cas(TestCase):

    def setUp(self):
        call_command('loaddata', 'fixture_users.json', verbosity=1)
        call_command('loaddata', 'xxx_tests_xxxx.yaml', 
        verbosity=1)

    def test_dossier_duplicate(self) :
        request = self.client.get('/dossier/3/copier/', follow = True)
        request.user = User.objects.get(id=3)
        pk = 3
        response = dossier_duplicate(request, pk)
        response.client = Client()
        response.client.login(username='xxxx', password='xxxxx')

        self.assertRedirects(response, '/mes_dossiers/', status_code=302, 
        target_status_code=200, fetch_redirect_response=True)
Rubadub answered 9/11, 2017 at 17:44 Comment(1)
Doesn't django.tests.TestCase.client.get give you a a response object?Barham
K
5

I reach this question via google and I have a similar issue with testing redirect.

But my Django is v2.2 and the accepted answer cites a v1.7 which is no longer supported

I then google some more and found this code block at https://docs.djangoproject.com/en/2.2/topics/testing/tools/#django.test.SimpleTestCase.settings

from django.test import TestCase

class LoginTestCase(TestCase):

    def test_login(self):

        # First check for the default behavior
        response = self.client.get('/sekrit/')
        self.assertRedirects(response, '/accounts/login/?next=/sekrit/')

I modified for my own use which works.

For the OP case, this is how I believe should work if the OP uses 2.2

def test_dossier_duplicate(self) :
    response = self.client.get('/dossier/3/copier/')
    self.assertRedirects(response, '/mes_dossiers/')

I am leaving this here. In case future readers have a similar question but have it for Django v2.2

Kimbell answered 4/6, 2020 at 5:12 Comment(0)
L
3

To test redirects you should use the test client instead of RequestFactory.

The API for the RequestFactory is a slightly restricted subset of the test client API:

  • It only has access to the HTTP methods get(), post(), put(), delete(), head(), options(), and trace().

  • These methods accept all the same arguments except for follows. Since this is just a factory for producing requests, it’s up to you to handle the response.

https://docs.djangoproject.com/en/1.11/topics/testing/advanced/#the-request-factory

Try changing self.factory.get to self.client.get

    response = self.client.get('/dossier/3/copier/', follow = True)
Lenrow answered 30/10, 2017 at 21:48 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.