繁体   English   中英

Django 测试客户端不处理异常?

[英]Django test client does not handle exceptions?

我需要使用 django 测试虚拟客户端为 Django 中的自定义 handler404 和 handler500 编写一些测试。 第一个很容易测试,而我对第二个有问题。

基本上,问题在于 Django 测试客户端没有捕获异常并且没有路由到正确的处理程序。 这是一个问题,因为我们需要测试是否使用了正确的自定义处理程序和模板。

我们有一个简单的中间件类来模拟测试异常:

  class HTTPStatusCodeMiddleware(object):
    def process_view(self, request, *args):
        if 'cookie_500_error' in request.COOKIES:
            raise Exception('Test exception')

上面的代码适用于浏览器中的手动测试。

现在,测试是:

  def test_404_template(self):                                                 
      c = Client()                                                             
      url = '/not_existing.html'                                               
      response = c.get(url)                                                    
      self.assertEqual(response.status_code, 404)  # success                  
      self.assertTemplateUsed(response, 'custom/404.html')  # success   

  def test_500_template(self):                                                 
      c = Client()                                                             
      c.cookies['cookie_500_error'] = '1'                                  
      response = c.get('/')  # here middleware raises exception!!!
      self.assertEqual(response.status_code, 500)
      self.assertTemplateUsed(response, 'custom/500.html')

任何的想法? 我没有选择使用硒。 谢谢!

Django 测试客户端仅处理一些异常(请参阅文档)。 所有其他人都在测试中可见,您可以测试它们;)

现在 Django 3.0 支持了

新的测试Client参数raise_request_exception允许控制在请求期间引发的异常是否也应在测试中引发。 为了向后兼容,该值默认为True 如果它是False并且发生异常,则测试客户端将返回一个带有属性exc_info的 500 响应,这是一个提供发生异常信息的元组。

c = Client(raise_request_exception=False)

有关文档中的信息

对于 Django 2.x,可以通过修补其store_exc_info方法来阻止测试客户端引发异常:

c = Client()                                                             
c.store_exc_info = lambda *args, **kw: None
response = c.get("/error")
assert response.status_code == 500

假设处理/error url 的视图引发异常,这将允许我们获得500 Server Error响应。

对于 Django>=3.0,应该使用raise_request_exception参数(如@CesarCanassa 回答中所述)

所以 django test Client 类在设计上不会捕获异常,这是一件好事。

由于问题具体是测试自定义 handler500,它是由自定义中间件在特定设置上设置的,只需将 request.urlconf 变量替换为自定义 urlconf 模块,解决方案是使用 RequestFactory 构建请求,并测试 request.urlconf.handler500看法:

在 custom/client1/urls.py

def handler500(request):
    data = {'client', 'client1 is sorry!'}
    ctx = RequestContext(request)
    content = render_to_string('client1/500.html', data, ctx)
    return http.HttpResponseServerError(content)

在测试/视图/test_error_pages.py

def test_500_template(self):
    req = RequestFactory().get('/')
    req.user = AnonymousUser()
    req.session = {}

    cust_mw = CustomUrlconfMiddleware()
    cust_mw.process_request(req)  # set the custom request.urlconf
    urlconf = importlib.import_module(req.urlconf)
    response = urlconf.handler500(req)
    self.assertEqual(response.status_code, 500)
    assert_str = '/static/img/custom/client1/'
    self.assertTrue(assert_str in response.content,
                    msg='500 template is not for client1. String {} is not in content'.format(assert_str))

好的,我在单元测试中使用PermissionDenied异常时遇到了类似的问题。 由于 Django 没有捕获它们,它导致我的测试崩溃而不是失败。 我确实想出了一个我还没有看到发布的简单解决方案,它是这样的:

示例视图:

from django.core.exceptions import PermissionDenied

class SampleView(object):
    def setup(request):
        if not request_is_authenticated(request):
            raise PermissionDenied

单元测试:

from django.core.exceptions import PermissionDenied

def test_permission(self):
    try:
        SampleView.setup(request)
    except PermissionDenied:
        print('Hallelujah no crashing!')

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM