Как можно протестировать пользовательские представления ошибок в django?

В документации Django приводится следующий пример для тестирования пользовательских представлений ошибок.

С учетом следующего примера, как вы собираетесь тестировать пользовательские server_error и csrf_failure представления? Я пытался запустить представление ошибки, используя несколько различных django.core.exceptions, однако пользовательское представление ошибки никогда не запускается.

Возврат HTTPResponse дает ошибку AssertionError: No templates used to render the response, что вполне логично. Однако когда я пытаюсь вывести ошибку, которая должна вызвать ошибку сервера, например raise ImproperlyConfigured, ошибка просто выводится в тесте.

Тестирование на отказ CSRF - это уже другая история, поскольку я чувствую, что даже не приблизился к этому.

# views.py

from django.views import defaults
from django.views.csrf import csrf_failure as csrf_failure_default

def server_error(request):
    template_name = 'wholesale/500.html'
    return defaults.server_error(
        request,
        template_name=template_name,
    )


def csrf_failure(request, reason=''):
    template_name = 'wholesale/403_csrf.html'
    return csrf_failure_default(
        request,
        reason=reason,
        template_name=template_name,
    )
# tests.py

from django.test import TestCase, override_settings
from . import views


def page_not_found_view(request):
    raise Http404


def server_error_view(request):
    # raise ImproperlyConfigured
    return HttpResponseServerError()


def bad_request_view(request):
    raise BadRequest


def permission_denied_view(request):
    raise PermissionDenied


def csrf_failure_view(request):
    return HttpResponse(status=HTTPStatus.FORBIDDEN)


urlpatterns = [
    path('404/', page_not_found_view),
    path('500/', server_error_view),
    path('400/', bad_request_view),
    path('403/', permission_denied_view),
    path('403_csrf/', csrf_failure_view),
]
handler404 = views.page_not_found
handler500 = views.server_error
handler400 = views.bad_request
handler403 = views.permission_denied


@override_settings(ROOT_URLCONF=__name__)
class CustomErrorViewTestCase(TestCase):
    def test_page_not_found_view(self):
        response = self.client.get('/404/')
        self.assertEqual(response.status_code, HTTPStatus.NOT_FOUND)
        self.assertTemplateUsed(response, 'wholesale/404.html')

    def test_server_error_view(self):
        response = self.client.get('/500/')
        self.assertEqual(response.status_code, HTTPStatus.INTERNAL_SERVER_ERROR)
        self.assertTemplateUsed(response, 'wholesale/500.html')

    def test_bad_request_view(self):
        response = self.client.get('/400/')
        self.assertEqual(response.status_code, HTTPStatus.BAD_REQUEST)
        self.assertTemplateUsed(response, 'wholesale/400.html')

    def test_permission_denied_view(self):
        response = self.client.get('/403/')
        self.assertEqual(response.status_code, HTTPStatus.FORBIDDEN)
        self.assertTemplateUsed(response, 'wholesale/403.html')

    def test_csrf_failure_view(self):
        response = self.client.get('/403_csrf/')
        self.assertEqual(response.status_code, HTTPStatus.FORBIDDEN)
        self.assertTemplateUsed(response, 'wholesale/403_csrf.html')

Я нашел ответ в документации в разделе создание запросов.

Аргумент raise_request_exception позволяет контролировать, должны ли исключения, возникающие во время запроса, также возникать в тесте. По умолчанию значение True.

Мое решение - переопределить это значение и установить его на False.

def test_custom_server_error_view(self):
    server_error_client = Client(raise_request_exception=False)
    response = server_error_client.get('/500/')
    self.assertEqual(response.status_code, HTTPStatus.INTERNAL_SERVER_ERROR)
    self.assertTemplateUsed(response, 'wholesale/500.html')

Аналогичная настройка может быть использована для проверки отказа CSRF.

def test_custom_csrf_failure_view(self):
    csrf_client = Client(enforce_csrf_checks=True)
    response = csrf_client.post('/403_csrf/')
    self.assertEqual(response.status_code, HTTPStatus.FORBIDDEN)
    self.assertTemplateUsed(response, 'wholesale/403_csrf.html')
Вернуться на верх