Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django test client does not handle exceptions?

I've the need to write some tests for custom handler404 and handler500 in Django, using django test dummy client. The first is easy to test while I have problems with the second.

Basically, problem is that Django test client does not catch the exception and does not route to the proper handler. This is a problem because we need to test that the right custom handler and template are used.

We have a simple middleware class to simulate exceptions for tests:

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

Code above works fine for manual testing in browser.

Now, tests are:

  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')

Any idea? I don't have the option to use selenium. Thanks!

like image 659
BangTheBank Avatar asked Feb 04 '15 16:02

BangTheBank


People also ask

How do I skip a Django test?

Just trick it to always skip with the argument True : @skipIf(True, "I don't want to run this test yet") def test_something(): ... If you are looking to simply not run certain test files, the best way is probably to use fab or other tool and run particular tests.

What is Django test client?

The test client is a Python class that acts as a dummy web browser, allowing you to test your views and interact with your Django-powered application programmatically.

How do I run test PY in Django?

Open /catalog/tests/test_models.py.from django. test import TestCase # Create your tests here. Often you will add a test class for each model/view/form you want to test, with individual methods for testing specific functionality.

What are Django exceptions and how do you handle it?

An exception is an abnormal event that leads to program failure. To deal with this situation, Django uses its own exception classes and supports all core Python exceptions as well. Django core exceptions classes are defined in django. core.


3 Answers

Django test client handles only some exceptions (see the docs). All the others are visible in the test and you can test them ;)

like image 136
Bruce Avatar answered Oct 11 '22 23:10

Bruce


This is now supported by Django 3.0

The new test Client argument raise_request_exception allows controlling whether or not exceptions raised during the request should also be raised in the test. The value defaults to True for backwards compatibility. If it is False and an exception occurs, the test client will return a 500 response with the attribute exc_info, a tuple providing information of the exception that occurred.

c = Client(raise_request_exception=False)

For information at the documentation

like image 5
Cesar Canassa Avatar answered Oct 11 '22 21:10

Cesar Canassa


For Django 2.x, the test client can be stopped from raising exceptions by patching its store_exc_info method:

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

Assuming that the view handling the /error url raises an exception, this would allow us to get the 500 Server Error response.

For Django>=3.0, the raise_request_exception parameter should be used, instead (as mentioned in @CesarCanassa answer)

like image 2
Xavier Martinez-Hidalgo Avatar answered Oct 11 '22 23:10

Xavier Martinez-Hidalgo