46

I'm trying to setup email error logging and I want to test it.

Whats an easy way to trigger a 500 error in Django? This surprisingly has not been discussed here yet.

alecxe
  • 462,703
  • 120
  • 1,088
  • 1,195
User
  • 23,729
  • 38
  • 124
  • 207
  • When you say "test", do you just really mean - try it out? The answer you've accepted is not reliable enough - you'd better have an actual "test" that is running in an automated way. – alecxe Jul 09 '14 at 19:41
  • If I request that view in a browser, it will get me the 500 error I'm after – User Jul 09 '14 at 19:47
  • Sure, next time you break your logging configuration on production - you would think about having tests. See [Is Unit Testing worth the effort?](http://stackoverflow.com/questions/67299/is-unit-testing-worth-the-effort). – alecxe Jul 09 '14 at 20:13
  • Unit tests are cool, but sometimes you need manual testing to check if a log notification would trigger a spam filter in your corporate network. – xyzman Apr 23 '15 at 09:13
  • Even if you have a unit test, there are still valid reasons to want to run this test manually. – Akaisteph7 Jun 27 '23 at 14:46

4 Answers4

67

A test view like this will work:

from django.http import HttpResponse

def my_test_500_view(request):
    # Return an "Internal Server Error" 500 response code.
    return HttpResponse(status=500)

or use the baked in error class:

from django.http import HttpResponseServerError
def my_test_500_view(request):
        # Return an "Internal Server Error" 500 response code.
        return HttpResponseServerError()
agconti
  • 17,780
  • 15
  • 80
  • 114
  • This does not do @transaction.atomic rollback. Is there a way we can do that, except raising an exception. – Sufiyan Ansari May 29 '20 at 07:07
  • This just returns an empty page for me. My 404-page works fine, but if I try call this view with a 404-exception, the page is just plain empty – CutePoison May 13 '21 at 15:55
22

Raising an appropriate Exception is the most robust way to test this. Returning an HttpResponse of any variety, as in @agconti 's answer, will not allow you to test the behavior of error handling. You'll just see a blank page. Raising an exception triggers both the correct response code and the internal Django behavior you expect with a "real" error.

Response code 500 represents the server not knowing what to do. The easiest way is to write into your test or test-view raise Exception('Make response code 500!').

Most other errors should be raised with exceptions designed to trigger specific response codes. Here's the complete list of Django exceptions that you might raise.

Shaun Overton
  • 601
  • 1
  • 9
  • 16
7

Old question, but I hope this helps someone in the future. The accepted answer doesn't really answer the original question... You can do this with django rest framework easily by raising ApiException:

from rest_framework.exceptions import APIException

try:
   ...
except ...:
    raise APIException('custom exception message')

This will return a response with status 500 from your view. Pretty useful if you are calling another function from your API and you don't want to manage return values from this function to decide if returning a response with status 500. You can use it like this:

raise ApiException

And the default response message (at the time of writing this) will be 'A server error occurred.'.

There's a few predefined ApiException subclasses to raise different kinds of errors, check the file rest_framework.exceptions, if you need one that is not in there, you can extend ApiException like this:

from rest_framework.exceptions import APIException


class YourCustomApiExceptionName(APIException):
    def __init__(self, status, detail):
        self.status_code = status
        self.detail = detail

Usage:

raise YourCustomApiExceptionName(100, 'continue')

You can also define custom status and detail but wouldn't make much sense in most cases.

EDIT:

If for some reason you are working without DRF, you can just copy the APIException code instead of installing the DRF package:

https://github.com/encode/django-rest-framework/blob/4f7e9ed3bbb0fb3567884ef4e3d340bc2f77bc68/rest_framework/exceptions.py#L99

nnov
  • 489
  • 6
  • 14
  • Note this does not come built-in but will be [a new package](https://www.django-rest-framework.org/) that will need to be installed. – Akaisteph7 Jun 27 '23 at 14:48
  • @Akaisteph7 you can just copy the code and do not install the package. – nnov Jul 02 '23 at 13:21
0

If you can or want to do without custom view-code, here is a variant that uses only urls.py:

# django urls.py

from django.urls import path
from django.views.defaults import server_error

urlpatterns = [
    path('500/', server_error),
]
tombreit
  • 1,199
  • 8
  • 27