首页 > 解决方案 > 无法将 override_settings 类装饰器与 setUpClass 和 tearDownClass Django 一起使用

问题描述

解决了

我正在尝试在 django 中编写单元测试。当与类方法一起使用时,我遇到了override_settings装饰器的不同行为。以下是不起作用的代码:setUpClasstearDownClass

import logging
from django.test import SimpleTestCase, override_settings
from django.http import Http404
from django.core.exceptions import SuspiciousOperation, PermissionDenied
from django.urls import path
from django.views.defaults import server_error

def http_400_view(request):
    """Test view for 400
    """
    raise SuspiciousOperation

def http_403_view(request):
    """Test view for 403
    """
    raise PermissionDenied

def http_404_view(request):
    """Test view for 404
    """
    raise Http404

def http_500_view(request):
    """Test view for 500
    """
    return server_error(request)

urlpatterns = [
    path('400/', http_400_view),
    path('403/', http_403_view),
    path('404/', http_404_view),
    path('500/', http_500_view),
]

@override_settings(ROOT_URLCONF=__name__)
class ErrorCodeHandlerTests(SimpleTestCase):
    """ Tests for error code handlers
    """
    @classmethod
    def setUpClass(cls):
        logging.disable(logging.CRITICAL)

    @classmethod
    def tearDownClass(cls):
        logging.disable(logging.NOTSET)

    status_codes = [400, 403, 404, 500]
    templates = ['400.html', '403.html', '404.html', '500.html']
    user_messages = ['Bad request', 'Permission denied', 'Page not found', 'Internal server error']

    def test_correct_html_rendered_on_error_code(self):
        """Test if correct template and error code exists in response after http errors
        """
        for i in range(len(self.status_codes)):
            with self.subTest(i=i):
                response = self.client.get('/' + str(self.status_codes[i]) + '/')
                self.assertTemplateUsed(response, self.templates[i])
                self.assertContains(
                    response,
                    self.user_messages[i],
                    status_code=self.status_codes[i],
                    html=True
                )

在上面的代码中,设置没有被覆盖,我得到所有 url 的 404。

以下是有效的代码:

import logging
from django.test import SimpleTestCase, override_settings
from django.http import Http404
from django.core.exceptions import SuspiciousOperation, PermissionDenied
from django.urls import path
from django.views.defaults import server_error

def http_400_view(request):
    """Test view for 400
    """
    raise SuspiciousOperation

def http_403_view(request):
    """Test view for 403
    """
    raise PermissionDenied

def http_404_view(request):
    """Test view for 404
    """
    raise Http404

def http_500_view(request):
    """Test view for 500
    """
    return server_error(request)

urlpatterns = [
    path('400/', http_400_view),
    path('403/', http_403_view),
    path('404/', http_404_view),
    path('500/', http_500_view),
]

class ErrorCodeHandlerTests(SimpleTestCase):
    """ Tests for error code handlers
    """
    @classmethod
    def setUpClass(cls):
        logging.disable(logging.CRITICAL)

    @classmethod
    def tearDownClass(cls):
        logging.disable(logging.NOTSET)

    status_codes = [400, 403, 404, 500]
    templates = ['400.html', '403.html', '404.html', '500.html']
    user_messages = ['Bad request', 'Permission denied', 'Page not found', 'Internal server error']

    @override_settings(ROOT_URLCONF=__name__)
    def test_correct_html_rendered_on_error_code(self):
        """Test if correct template and error code exists in response after http errors
        """
        for i in range(len(self.status_codes)):
            with self.subTest(i=i):
                response = self.client.get('/' + str(self.status_codes[i]) + '/')
                self.assertTemplateUsed(response, self.templates[i])
                self.assertContains(
                    response,
                    self.user_messages[i],
                    status_code=self.status_codes[i],
                    html=True
                )

另外,如果我不使用setUpClassand tearDownClass,则override_settings在这两种情况下都可以使用。这里可能的原因是什么?

标签: pythondjangopython-unittestdjango-unittest

解决方案


我弄清楚了这个问题。问题是,setUpClasstearDownClass必须调用相应的基类方法super().setUpClass()才能super().tearDownClass()工作override_settings


推荐阅读