Search code examples
pythondjangodjango-testingdjango-tests

Django, Testing Redirects to External Pages


I have a routing rule in my Django app for downloads that redirect to a external CDN. I am now writing tests for my app, and I want to test that the route does successfully redirect to the configured url in my Django settings. Here is a simplified example that should help explain what I'm trying to do:

from django.test import SimpleTestCase
from django.test.client import Client
from django.conf import settings

class MyTestCase(SimpleTestCase):
    def setUp(self):
        self.client = Client()
    def test_download(self):
        response = self.client.get('/download/mac/')
        self.assertRedirects(response, settings.URLS.get('mac'))

Now this doesn't work, the redirect gets a 404 even though when I print settings.DOWNLOAD_URL in this method it is correct, and a copy/paste into the browser proves it works. I started to look into why it wasn't working, and I noticed this in the Django source code:

Note that assertRedirects won't work for external links since it uses TestClient to do a request.

So then, how does one test these redirects? I'm not looking for anything super fancy, what I expect to check is the response's status_code and location. I saw that response has a follow parameter, and tried something like this, but it still didn't work:

    def test_download(self):
        response = self.client.get('/download/mac/', follow=True)
        self.assertEqual(response.status_code, 302)
        self.assertEqual(response['Location'], settings.URLS.get('mac')

It was requested that I include the relevant parts from my urls.py and views.py, here they are:

# urls.py
from django.conf.urls import patterns, url
urlpatterns = patterns('myapp.views',
    url(r'^download/(?P<platform>\w+)/$', 'download_app', name='download'),
)

#views.py
from django.conf import settings
from django.shortcuts import redirect
from django.http import Http404

def download_app(request, platform):
    if platform in settings.URLS:
        return redirect( settings.URLS.get(platform) )
    else:
        raise Http404

Any help in solving this would be much appreciated. Thanks in advance.


Solution

  • Probably the original poster has solved his problems and moved on long ago, but the solution here is to not specify follow=True as he did in the alternative proposal that didn't work either.

    The following will simply check that the view being tested redirects as expected, without relying on the external resources.

    def test_download(self):
        response = self.client.get('/download/mac')
    
        self.assertEqual(response.status_code, 302)
        self.assertEqual(response['Location'], 'http://external/resource')
    

    In Django 1.7 assertRedirect got a new parameter fetch_redirect_response which can be set to False to get the same effect, but I haven't tried it myself.