2012-01-22 8 views
7

Estoy usando el cliente de prueba Django, django.test.client.Client, para probar algunas vistas en una aplicación Django. En particular, estoy probando un caso en el que la vista llama a un método get_object_or_404 y el objeto no está allí, por lo que debería devolverse un 404.La prueba del 404 esperado con el cliente de prueba Django conduce a una excepción no controlada

Mi código de prueba es el siguiente:

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) 

Sin embargo, lo que estoy haciendo en cambio, es un error de excepción no controlada en el código de la vista:

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. 

De acuerdo con la Django 1.3 docs

The only exceptions that are not visible to the test client are Http404, PermissionDenied and SystemExit. 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.

¿Por qué Django no captura la excepción Http404 en este caso?

Tenga en cuenta que (de conformidad con los documentos), la excepción es no que se envía al cliente de prueba. Si trato de capturar la excepción del lado del cliente:

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

me sale el mismo error, así como un error adicional:

AssertionError: Http404 not raised 
+0

Pero, según su respuesta, django debe devolver un código de respuesta 404, es un error de django, ¿no? – AlejandroPerezLillo

Respuesta

6

Sé que esto es de hace un tiempo, pero lo resolví, así que pensé que valía la pena compartirlo. Lo que debe hacer es personalizar el controlador de errores en su código. Por ejemplo, tengo:

en urls.py:

from myapp.views import error_handler 
handler404 = error_handler.error404 

y la función de error404:

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

    return HttpResponseNotFound(html) 

Si envía un objeto HttpResponseNotFound, se interpretará como un código de estado 404.

EDITAR

En las nuevas versiones de Django está bien sólo para poner un 404.html en el directorio de plantillas. El controlador anterior solo es necesario si necesita más lógica que solo mostrar la página de error.

2

Tras una inspección más, parece que la prueba está pasando como está escrito: el mensaje de error en realidad no corresponde a una falla de prueba.

Cuestiones relacionadas