2012-01-22 15 views
7

Używam klienta testowego Django, django.test.client.Client, do testowania niektórych widoków w aplikacji Django. W szczególności testuję przypadek, w którym widok wywołuje metodę get_object_or_404, a obiekt nie istnieje, dlatego należy zwrócić 404.Testowanie pod kątem oczekiwanego 404 z klientem testowym Django prowadzi do nieobsługiwanego wyjątku

Mój kod testowy wygląda następująco:

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) 

Jednak to, co dostaję w zamian jest nieobsługiwany wyjątek błędu w kodzie Widok:

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. 

Według 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.

Dlaczego Django nie przyjmuje w tym przypadku wyjątku Http404?

Należy zauważyć, że (zgodnie z dokumentami), wyjątek stanowi , a nie jest przesyłany do klienta testowego. Gdy próbuję złapać wyjątek po stronie klienta:

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

otrzymuję ten sam błąd, jak również dodatkowy błąd:

AssertionError: Http404 not raised 
+0

Ale, zgodnie z twoją odpowiedzią, django musi zwrócić kod odpowiedzi 404, to jest błąd django, nie? – AlejandroPerezLillo

Odpowiedz

6

Wiem, że to jakiś czas temu, ale rozwiązałem to, więc pomyślałem, że warto się nim dzielić. To, co musisz zrobić, to dostosować obsługę błędów w kodzie. Na przykład mam:

w urls.py:

from myapp.views import error_handler 
handler404 = error_handler.error404 

i error404 funkcję:

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

    return HttpResponseNotFound(html) 

Jeśli wyślesz HttpResponseNotFound obiekt będzie interpretować jako kod 404 stanu.

EDIT

W nowszych wersjach django jest ok tylko umieścić 404.html w katalogu szablonów. Powyższy kontroler jest potrzebny tylko wtedy, gdy potrzebujesz więcej logiki, niż tylko pokazuje stronę błędu.

2

Po dalszej inspekcji, wygląda test przechodzi jak napisano: komunikat o błędzie w rzeczywistości nie odpowiada awarii testu.