Django 单元测试句柄 PermissionDenied
Django unittest handle PermissionDenied
正如文档所说 https://docs.djangoproject.com/en/2.2/topics/testing/tools/#exceptions;
The only exceptions that are not visible to the test client are Http404
, PermissionDenied
, SystemExit
, and SuspiciousOperation
. Django catches these exceptions internally and converts them into the appropriate HTTP response codes. In these cases, you can check response.status_code
in your test.
我处理了一个自定义登录 mixin,用于向已登录但无权访问该页面的用户引发错误。
class LoginQuizMarkerMixin(LoginRequiredMixin):
def dispatch(self, *args, **kwargs):
if self.request.user.is_authenticated:
if not self.request.user.has_perm('quizzes.view_sittings'):
raise PermissionDenied("You don't have any access to this page.")
return super().dispatch(*args, **kwargs)
我的 unitest,它工作正常。
class TestQuestionMarking(TestCase):
def setUp(self):
self.c1 = Category.objects.create_category(name='elderberries')
self.student = User.objects.create_user(username='student',
email='student@rebels.com',
password='top_secret')
self.teacher = User.objects.create_user(username='teacher',
email='teacher@jedis.com',
password='use_d@_force')
self.teacher.user_permissions.add(Permission.objects.get(codename='view_sittings'))
....
def test_paper_marking_list_view(self):
# should be 302 (redirection)
marking_url = reverse('quizzes:quiz_marking')
response = self.client.get(marking_url)
print('response1', response)
# should be 403 (permission denied)
self.client.login(username='student', password='top_secret')
response = self.client.get(marking_url)
print('response2', response)
# should be 200 (allowed)
self.client.login(username='teacher', password='use_d@_force')
response = self.client.get(marking_url)
print('response3', response)
但不知何故,它是 PermissionDenied
的错误,它显示了这样的错误:
docker-compose -f local.yml run --rm django python manage.py test labs.tests.quizzes.test_views.TestQuestionMarking.test_paper_marking_list_view
response1 <HttpResponseRedirect status_code=302, "text/html; charset=utf-8", url="/accounts/login/?next=/quizzes/marking/">
WARNING 2021-02-04 00:28:44,270 log 1 139681767683904 [log.py:222] Forbidden (Permission denied): /quizzes/marking/
Traceback (most recent call last):
File "/usr/local/lib/python3.8/site-packages/django/core/handlers/exception.py", line 34, in inner
response = get_response(request)
File "/usr/local/lib/python3.8/site-packages/django/core/handlers/base.py", line 115, in _get_response
response = self.process_exception_by_middleware(e, request)
File "/usr/local/lib/python3.8/site-packages/django/core/handlers/base.py", line 113, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/usr/local/lib/python3.8/contextlib.py", line 75, in inner
return func(*args, **kwds)
File "/usr/local/lib/python3.8/site-packages/django/views/generic/base.py", line 71, in view
return self.dispatch(request, *args, **kwargs)
File "/app/my_app/quizzes/views.py", line 37, in dispatch
raise PermissionDenied("You don't have any access to this page.")
django.core.exceptions.PermissionDenied: You don't have any access to this page.
response2 <HttpResponseForbidden status_code=403, "text/html; charset=utf-8">
response3 <TemplateResponse status_code=200, "text/html; charset=utf-8">
而我所期望的仍然是错误,没有像上面那样出现。应该像下面这样:
response1 <HttpResponseRedirect status_code=302, "text/html; charset=utf-8", url="/accounts/login/?next=/quizzes/marking/">
response2 <HttpResponseForbidden status_code=403, "text/html; charset=utf-8">
response3 <TemplateResponse status_code=200, "text/html; charset=utf-8">
但是,在另一个测试中,当我尝试用 raise Http404
更改它时,它工作正常:
class LoginQuizMarkerMixin(LoginRequiredMixin):
def dispatch(self, *args, **kwargs):
if self.request.user.is_authenticated:
if not self.request.user.has_perm('quizzes.view_sittings'):
# raise PermissionDenied("You don't have any access to this page.")
raise Http404
return super().dispatch(*args, **kwargs)
控制台输出:
response1 <HttpResponseRedirect status_code=302, "text/html; charset=utf-8", url="/accounts/login/?next=/quizzes/marking/">
WARNING 2021-02-04 13:39:05,368 log 1 139683990402880 [log.py:222] Not Found: /quizzes/marking/
response2 <HttpResponseNotFound status_code=404, "text/html; charset=utf-8">
response3 <TemplateResponse status_code=200, "text/html; charset=utf-8">
我通过在测试模式设置中禁用我的日志来解决这个问题。
docker-compose -f local.yml run --rm django python manage.py test --settings=config.settings.test
在我的 config/settings/test.py
;
里面
LOGGING = {}
Related issue: How can I disable logging while running unit tests in Python Django?
正如文档所说 https://docs.djangoproject.com/en/2.2/topics/testing/tools/#exceptions;
The only exceptions that are not visible to the test client are
Http404
,PermissionDenied
,SystemExit
, andSuspiciousOperation
. Django catches these exceptions internally and converts them into the appropriate HTTP response codes. In these cases, you can checkresponse.status_code
in your test.
我处理了一个自定义登录 mixin,用于向已登录但无权访问该页面的用户引发错误。
class LoginQuizMarkerMixin(LoginRequiredMixin):
def dispatch(self, *args, **kwargs):
if self.request.user.is_authenticated:
if not self.request.user.has_perm('quizzes.view_sittings'):
raise PermissionDenied("You don't have any access to this page.")
return super().dispatch(*args, **kwargs)
我的 unitest,它工作正常。
class TestQuestionMarking(TestCase):
def setUp(self):
self.c1 = Category.objects.create_category(name='elderberries')
self.student = User.objects.create_user(username='student',
email='student@rebels.com',
password='top_secret')
self.teacher = User.objects.create_user(username='teacher',
email='teacher@jedis.com',
password='use_d@_force')
self.teacher.user_permissions.add(Permission.objects.get(codename='view_sittings'))
....
def test_paper_marking_list_view(self):
# should be 302 (redirection)
marking_url = reverse('quizzes:quiz_marking')
response = self.client.get(marking_url)
print('response1', response)
# should be 403 (permission denied)
self.client.login(username='student', password='top_secret')
response = self.client.get(marking_url)
print('response2', response)
# should be 200 (allowed)
self.client.login(username='teacher', password='use_d@_force')
response = self.client.get(marking_url)
print('response3', response)
但不知何故,它是 PermissionDenied
的错误,它显示了这样的错误:
docker-compose -f local.yml run --rm django python manage.py test labs.tests.quizzes.test_views.TestQuestionMarking.test_paper_marking_list_view
response1 <HttpResponseRedirect status_code=302, "text/html; charset=utf-8", url="/accounts/login/?next=/quizzes/marking/">
WARNING 2021-02-04 00:28:44,270 log 1 139681767683904 [log.py:222] Forbidden (Permission denied): /quizzes/marking/
Traceback (most recent call last):
File "/usr/local/lib/python3.8/site-packages/django/core/handlers/exception.py", line 34, in inner
response = get_response(request)
File "/usr/local/lib/python3.8/site-packages/django/core/handlers/base.py", line 115, in _get_response
response = self.process_exception_by_middleware(e, request)
File "/usr/local/lib/python3.8/site-packages/django/core/handlers/base.py", line 113, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/usr/local/lib/python3.8/contextlib.py", line 75, in inner
return func(*args, **kwds)
File "/usr/local/lib/python3.8/site-packages/django/views/generic/base.py", line 71, in view
return self.dispatch(request, *args, **kwargs)
File "/app/my_app/quizzes/views.py", line 37, in dispatch
raise PermissionDenied("You don't have any access to this page.")
django.core.exceptions.PermissionDenied: You don't have any access to this page.
response2 <HttpResponseForbidden status_code=403, "text/html; charset=utf-8">
response3 <TemplateResponse status_code=200, "text/html; charset=utf-8">
而我所期望的仍然是错误,没有像上面那样出现。应该像下面这样:
response1 <HttpResponseRedirect status_code=302, "text/html; charset=utf-8", url="/accounts/login/?next=/quizzes/marking/">
response2 <HttpResponseForbidden status_code=403, "text/html; charset=utf-8">
response3 <TemplateResponse status_code=200, "text/html; charset=utf-8">
但是,在另一个测试中,当我尝试用 raise Http404
更改它时,它工作正常:
class LoginQuizMarkerMixin(LoginRequiredMixin):
def dispatch(self, *args, **kwargs):
if self.request.user.is_authenticated:
if not self.request.user.has_perm('quizzes.view_sittings'):
# raise PermissionDenied("You don't have any access to this page.")
raise Http404
return super().dispatch(*args, **kwargs)
控制台输出:
response1 <HttpResponseRedirect status_code=302, "text/html; charset=utf-8", url="/accounts/login/?next=/quizzes/marking/">
WARNING 2021-02-04 13:39:05,368 log 1 139683990402880 [log.py:222] Not Found: /quizzes/marking/
response2 <HttpResponseNotFound status_code=404, "text/html; charset=utf-8">
response3 <TemplateResponse status_code=200, "text/html; charset=utf-8">
我通过在测试模式设置中禁用我的日志来解决这个问题。
docker-compose -f local.yml run --rm django python manage.py test --settings=config.settings.test
在我的 config/settings/test.py
;
LOGGING = {}
Related issue: How can I disable logging while running unit tests in Python Django?