Django单元测试触发PermissionDenied时输出异常堆栈的问题排查
问题根因
该现象完全来自Django 2.2版本框架对两类HTTP异常的内置日志记录逻辑差异,和自定义Mixin、测试用例的编写逻辑无关,测试本身的断言能力不受任何影响。
两类异常都会被测试客户端正常捕获并转换为对应HTTP状态码,符合框架的测试工具设计,不存在异常未被拦截的问题。
两类异常的日志处理细节差异
- 框架捕获
Http404异常时,会将事件记录到django.request日志器下,日志调用默认不携带异常栈信息(未开启exc_info参数),因此输出仅为一行简短的404提示,不会附带完整调用堆栈。 - 框架捕获
PermissionDenied异常时,会将事件记录到django.security安全类日志器下,日志调用显式开启了异常栈记录。因为权限拒绝事件属于安全类重点排查项,框架默认设计要求输出完整调用路径,方便问题排查。
冗余堆栈的关闭方法
如果不需要测试环境输出这类安全日志的堆栈信息,不需要改动业务代码,可通过以下方式调整:
- 在测试对应的日志配置中,将
django.security日志器的输出级别调整为高于WARNING(比如设置为ERROR),直接过滤掉权限拒绝的WARNING级日志内容; - 运行测试时通过Django命令参数临时禁用日志输出,原有命令可直接追加对应参数:
docker-compose -f local.yml run --rm django python manage.py test labs.tests.quizzes.test_views.TestQuestionMarking.test_paper_marking_list_view --disable-logging
补充说明:额外输出的堆栈只是日志层面的附加信息,不会打断测试流程,也不会改变最终返回的响应对象属性,测试用例中对
response.status_code的断言逻辑可以正常生效。
内容的提问来源于stack exchange,提问作者binpy
相关产品推荐
相关产品推荐

