Fixed #18707 -- Added support for the test client to return 500 responses.
This commit is contained in:
parent
7071f8f272
commit
7feddd878c
|
@ -440,9 +440,10 @@ class Client(RequestFactory):
|
||||||
contexts and templates produced by a view, rather than the
|
contexts and templates produced by a view, rather than the
|
||||||
HTML rendered to the end-user.
|
HTML rendered to the end-user.
|
||||||
"""
|
"""
|
||||||
def __init__(self, enforce_csrf_checks=False, **defaults):
|
def __init__(self, enforce_csrf_checks=False, raise_request_exception=True, **defaults):
|
||||||
super().__init__(**defaults)
|
super().__init__(**defaults)
|
||||||
self.handler = ClientHandler(enforce_csrf_checks)
|
self.handler = ClientHandler(enforce_csrf_checks)
|
||||||
|
self.raise_request_exception = raise_request_exception
|
||||||
self.exc_info = None
|
self.exc_info = None
|
||||||
|
|
||||||
def store_exc_info(self, **kwargs):
|
def store_exc_info(self, **kwargs):
|
||||||
|
@ -497,10 +498,12 @@ class Client(RequestFactory):
|
||||||
# exception data, then re-raise the signalled exception.
|
# exception data, then re-raise the signalled exception.
|
||||||
# Also make sure that the signalled exception is cleared from
|
# Also make sure that the signalled exception is cleared from
|
||||||
# the local cache!
|
# the local cache!
|
||||||
|
response.exc_info = self.exc_info
|
||||||
if self.exc_info:
|
if self.exc_info:
|
||||||
_, exc_value, _ = self.exc_info
|
_, exc_value, _ = self.exc_info
|
||||||
self.exc_info = None
|
self.exc_info = None
|
||||||
raise exc_value
|
if self.raise_request_exception:
|
||||||
|
raise exc_value
|
||||||
|
|
||||||
# Save the client and request that stimulated the response.
|
# Save the client and request that stimulated the response.
|
||||||
response.client = self
|
response.client = self
|
||||||
|
|
|
@ -187,7 +187,13 @@ Templates
|
||||||
Tests
|
Tests
|
||||||
~~~~~
|
~~~~~
|
||||||
|
|
||||||
* ...
|
* The new test :class:`~django.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 :attr:`~django.test.Response.exc_info`, a tuple providing
|
||||||
|
information of the exception that occurred.
|
||||||
|
|
||||||
URLs
|
URLs
|
||||||
~~~~
|
~~~~
|
||||||
|
|
|
@ -128,6 +128,14 @@ Use the ``django.test.Client`` class to make requests.
|
||||||
The ``json_encoder`` argument allows setting a custom JSON encoder for
|
The ``json_encoder`` argument allows setting a custom JSON encoder for
|
||||||
the JSON serialization that's described in :meth:`post`.
|
the JSON serialization that's described in :meth:`post`.
|
||||||
|
|
||||||
|
The ``raise_request_exception`` argument allows controlling whether or not
|
||||||
|
exceptions raised during the request should also be raised in the test.
|
||||||
|
Defaults to ``True``.
|
||||||
|
|
||||||
|
.. versionadded:: 3.0
|
||||||
|
|
||||||
|
The ``raise_request_exception`` argument was added.
|
||||||
|
|
||||||
Once you have a ``Client`` instance, you can call any of the following
|
Once you have a ``Client`` instance, you can call any of the following
|
||||||
methods:
|
methods:
|
||||||
|
|
||||||
|
@ -476,6 +484,23 @@ Specifically, a ``Response`` object has the following attributes:
|
||||||
:attr:`~django.template.response.SimpleTemplateResponse.context_data`
|
:attr:`~django.template.response.SimpleTemplateResponse.context_data`
|
||||||
may be a suitable alternative on responses with that attribute.
|
may be a suitable alternative on responses with that attribute.
|
||||||
|
|
||||||
|
.. attribute:: exc_info
|
||||||
|
|
||||||
|
.. versionadded:: 3.0
|
||||||
|
|
||||||
|
A tuple of three values that provides information about the unhandled
|
||||||
|
exception, if any, that occurred during the view.
|
||||||
|
|
||||||
|
The values are (type, value, traceback), the same as returned by
|
||||||
|
Python's :func:`sys.exc_info`. Their meanings are:
|
||||||
|
|
||||||
|
- *type*: The type of the exception.
|
||||||
|
- *value*: The exception instance.
|
||||||
|
- *traceback*: A traceback object which encapsulates the call stack at
|
||||||
|
the point where the exception originally occurred.
|
||||||
|
|
||||||
|
If no exception occurred, then ``exc_info`` will be ``None``.
|
||||||
|
|
||||||
.. method:: json(**kwargs)
|
.. method:: json(**kwargs)
|
||||||
|
|
||||||
The body of the response, parsed as JSON. Extra keyword arguments are
|
The body of the response, parsed as JSON. Extra keyword arguments are
|
||||||
|
@ -544,9 +569,10 @@ content type of a response using ``response['Content-Type']``.
|
||||||
Exceptions
|
Exceptions
|
||||||
----------
|
----------
|
||||||
|
|
||||||
If you point the test client at a view that raises an exception, that exception
|
If you point the test client at a view that raises an exception and
|
||||||
will be visible in the test case. You can then use a standard ``try ... except``
|
``Client.raise_request_exception`` is ``True``, that exception will be visible
|
||||||
block or :meth:`~unittest.TestCase.assertRaises` to test for exceptions.
|
in the test case. You can then use a standard ``try ... except`` block or
|
||||||
|
:meth:`~unittest.TestCase.assertRaises` to test for exceptions.
|
||||||
|
|
||||||
The only exceptions that are not visible to the test client are
|
The only exceptions that are not visible to the test client are
|
||||||
:class:`~django.http.Http404`,
|
:class:`~django.http.Http404`,
|
||||||
|
@ -555,6 +581,11 @@ The only exceptions that are not visible to the test client are
|
||||||
exceptions internally and converts them into the appropriate HTTP response
|
exceptions internally and converts them into the appropriate HTTP response
|
||||||
codes. In these cases, you can check ``response.status_code`` in your test.
|
codes. In these cases, you can check ``response.status_code`` in your test.
|
||||||
|
|
||||||
|
If ``Client.raise_request_exception`` is ``False``, the test client will return a
|
||||||
|
500 response as would be returned to a browser. The response has the attribute
|
||||||
|
:attr:`~Response.exc_info` to provide information about the unhandled
|
||||||
|
exception.
|
||||||
|
|
||||||
Persistent state
|
Persistent state
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
|
|
|
@ -759,6 +759,20 @@ class ClientTest(TestCase):
|
||||||
with self.assertRaises(KeyError):
|
with self.assertRaises(KeyError):
|
||||||
self.client.get("/broken_view/")
|
self.client.get("/broken_view/")
|
||||||
|
|
||||||
|
def test_exc_info(self):
|
||||||
|
client = Client(raise_request_exception=False)
|
||||||
|
response = client.get("/broken_view/")
|
||||||
|
self.assertEqual(response.status_code, 500)
|
||||||
|
exc_type, exc_value, exc_traceback = response.exc_info
|
||||||
|
self.assertIs(exc_type, KeyError)
|
||||||
|
self.assertIsInstance(exc_value, KeyError)
|
||||||
|
self.assertEqual(str(exc_value), "'Oops! Looks like you wrote some bad code.'")
|
||||||
|
self.assertIsNotNone(exc_traceback)
|
||||||
|
|
||||||
|
def test_exc_info_none(self):
|
||||||
|
response = self.client.get("/get_view/")
|
||||||
|
self.assertIsNone(response.exc_info)
|
||||||
|
|
||||||
def test_mail_sending(self):
|
def test_mail_sending(self):
|
||||||
"Mail is redirected to a dummy outbox during test setup"
|
"Mail is redirected to a dummy outbox during test setup"
|
||||||
response = self.client.get('/mail_sending_view/')
|
response = self.client.get('/mail_sending_view/')
|
||||||
|
|
Loading…
Reference in New Issue