Search code examples
djangounit-testinghttp-status-code-403http-error

How can I test a 403 error?


I have a Test Class, that test the access of all page with different user.

Those access are defined by decorator on each of my views.

views.py :

@login_required
def afficher(request):
    ...
    ...

@creation_permission_required
def ajouter(request):
    ...
    ...

Some of these decorator are defined by me.

decorators.py :

def creation_permission_required(function):
    @wraps(function)
    @login_required
    def decorateur(request, *k, **a):
        user = get_object_or_404(User, username__iexact=request.user.username)
        if user.is_superuser or user.get_profile().creation:
            return function(request, *k, **a)
        else:
            return HttpResponseRedirect(reverse("non_autorise"))# <--- PROBLEM
    return decorateur
    return function

When I test them, I use the status_code attribute to verify if the user can access or not the page

test.py :

c = Client()
c.login(username='aucun', password='aucun')
for url in self.url_aucun:
    r = c.get(reverse(url['url'], args=url['args']))
    self.assertEqual(r.status_code, 200)
for url in self.url_creation:
    r = c.get(reverse(url['url'], args=url['args']))
    self.assertEqual(r.status_code, 302)      # <--- SECOND PROBLEM 

When a user doesn't have the right to access a page, the page should return a 403 error (forbidden). How can I do to test 403 instead of 302 ?

EDIT : I tried to use HttpResponseForbidden(reverse("non_autorise")), but couldn't get any content. So then I tried to make my own HttpResponse which is an exact copy of HttpResponseRedirect but with another status_code (403) still didn't get any content...

decorators.py :

class HttpResponseTest(HttpResponse):
    def __init__(self, redirect_to):
        super(HttpResponseTest, self).__init__()
        self['Location'] = iri_to_uri(redirect_to)
        self.status_code = 403

def creation_permission_required(function):
    @wraps(function)
    @login_required
    def decorateur(request, *k, **a):
        user = get_object_or_404(User, username__iexact=request.user.username)
        if user.is_superuser or user.get_profile().creation:
            return function(request, *k, **a)
        else:
            return HttpResponseTest(reverse("non_autorise"))# <--- PROBLEM
    return decorateur
    return function

Solution

  • If you want a 403 response, you can raise a PermissionDenied exception in your decorator if you are using Django 1.4. Alternatively, you can return a HttpResponseForbidden in your decorator. You will also have to build a custom login_required decorator.