7

我正在使用 Django 测试客户端django.test.client.Client来测试 Django 应用程序中的一些视图。特别是,我正在测试视图调用get_object_or_404方法但对象不存在的情况,因此应该返回 404。

我的测试代码如下所示:

class ViewTests(TestCase):
    fixtures=['test.json']

    def test_thing_not_there_get(self):
        url = '/foo/30afda98-b9d7-4e26-a59a-76ac1b6a001f/'
        c = django.test.client.Client()
        response = c.get(url)
        self.assertEqual(response.status_code, 404)

但是,我得到的是视图代码中未处理的异常错误:

python projects/unittests/manage.py test 
Creating test database for alias 'default'...
......ERROR:root:Unhandled Exception on request for http://testserver/foo/30afda98-b9d7-4e26-a59a-76ac1b6a001f/
Traceback (most recent call last):
  File "/Users/lorin/.virtualenvs/myvenv/lib/python2.7/site-packages/django/core/handlers/base.py", line 111, in get_response
    response = callback(request, *callback_args, **callback_kwargs)
  File "/Users/lorin/.virtualenvs/myvenv/lib/python2.7/site-packages/django/views/decorators/csrf.py", line 39, in wrapped_view
    resp = view_func(*args, **kwargs)
  File "/Users/lorin/.virtualenvs/myvenv/lib/python2.7/site-packages/django/views/decorators/csrf.py", line 52, in wrapped_view
    return view_func(*args, **kwargs)
  File "/Users/lorin/django-myvenv/apps/myvenv_desktop/views.py", line 85, in foo_view
    instance = get_object_or_404(Foo, uuid=foo_uuid)
  File "/Users/lorin/.virtualenvs/myvenv/lib/python2.7/site-packages/django/shortcuts/__init__.py", line 115, in get_object_or_404
    raise Http404('No %s matches the given query.' % queryset.model._meta.object_name)
Http404: No Foo matches the given query.

根据Django 1.3 文档

测试客户端不可见的唯一例外是 Http404、PermissionDenied 和 SystemExit。Django 在内部捕获这些异常并将它们转换为适当的 HTTP 响应代码。在这些情况下,您可以在测试中检查 response.status_code。

在这种情况下,为什么 Django 没有捕获 Http404 异常?

请注意(与文档一致),异常不会被抛出到测试客户端。如果我尝试在客户端捕获异常:

with self.assertRaises(django.http.Http404):
    response = c.get(url)

我得到同样的错误,以及一个额外的错误:

AssertionError: Http404 not raised
4

2 回答 2

6

我知道这是不久前的,但我解决了这个问题,所以我认为值得分享。您需要做的是在您的代码中自定义错误处理程序。例如,我有:

在 urls.py 中:

from myapp.views import error_handler
handler404 = error_handler.error404

和函数error404:

from django.http import HttpResponseNotFound
def error404(request):
    t = loader.get_template('404.html')
    html = t.render(Context())

    return HttpResponseNotFound(html)

如果您发送一个HttpResponseNotFound对象,它将被解释为 404 状态码。

编辑

在较新版本的 django 中,只需将 a404.html放在模板目录中即可。仅当您需要更多逻辑而不仅仅是显示错误页面时,才需要上述控制器。

于 2013-02-21T15:39:21.413 回答
2

经过进一步检查,测试看起来就像写的那样通过了:错误消息实际上并不对应于测试失败。

于 2012-01-22T12:50:46.683 回答