mirror of
https://github.com/django/django.git
synced 2025-08-03 18:38:50 +00:00
Fixed #31224 -- Added support for asynchronous views and middleware.
This implements support for asynchronous views, asynchronous tests, asynchronous middleware, and an asynchronous test client.
This commit is contained in:
parent
3f7e4b16bf
commit
fc0fa72ff4
30 changed files with 1344 additions and 214 deletions
|
@ -67,6 +67,17 @@ The following is a unit test using the request factory::
|
|||
response = MyView.as_view()(request)
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
AsyncRequestFactory
|
||||
-------------------
|
||||
|
||||
``RequestFactory`` creates WSGI-like requests. If you want to create ASGI-like
|
||||
requests, including having a correct ASGI ``scope``, you can instead use
|
||||
``django.test.AsyncRequestFactory``.
|
||||
|
||||
This class is directly API-compatible with ``RequestFactory``, with the only
|
||||
difference being that it returns ``ASGIRequest`` instances rather than
|
||||
``WSGIRequest`` instances. All of its methods are still synchronous callables.
|
||||
|
||||
Testing class-based views
|
||||
=========================
|
||||
|
||||
|
|
|
@ -1755,6 +1755,62 @@ You can also exclude tests by tag. To run core tests if they are not slow:
|
|||
test has two tags and you select one of them and exclude the other, the test
|
||||
won't be run.
|
||||
|
||||
.. _async-tests:
|
||||
|
||||
Testing asynchronous code
|
||||
=========================
|
||||
|
||||
.. versionadded:: 3.1
|
||||
|
||||
If you merely want to test the output of your asynchronous views, the standard
|
||||
test client will run them inside their own asynchronous loop without any extra
|
||||
work needed on your part.
|
||||
|
||||
However, if you want to write fully-asynchronous tests for a Django project,
|
||||
you will need to take several things into account.
|
||||
|
||||
Firstly, your tests must be ``async def`` methods on the test class (in order
|
||||
to give them an asynchronous context). Django will automatically detect
|
||||
any ``async def`` tests and wrap them so they run in their own event loop.
|
||||
|
||||
If you are testing from an asynchronous function, you must also use the
|
||||
asynchronous test client. This is available as ``django.test.AsyncClient``,
|
||||
or as ``self.async_client`` on any test.
|
||||
|
||||
With the exception of the ``follow`` parameter, which is not supported,
|
||||
``AsyncClient`` has the same methods and signatures as the synchronous (normal)
|
||||
test client, but any method that makes a request must be awaited::
|
||||
|
||||
async def test_my_thing(self):
|
||||
response = await self.async_client.get('/some-url/')
|
||||
self.assertEqual(response.status_code, 200)
|
||||
|
||||
The asynchronous client can also call synchronous views; it runs through
|
||||
Django's :doc:`asynchronous request path </topics/async>`, which supports both.
|
||||
Any view called through the ``AsyncClient`` will get an ``ASGIRequest`` object
|
||||
for its ``request`` rather than the ``WSGIRequest`` that the normal client
|
||||
creates.
|
||||
|
||||
.. warning::
|
||||
|
||||
If you are using test decorators, they must be async-compatible to ensure
|
||||
they work correctly. Django's built-in decorators will behave correctly, but
|
||||
third-party ones may appear to not execute (they will "wrap" the wrong part
|
||||
of the execution flow and not your test).
|
||||
|
||||
If you need to use these decorators, then you should decorate your test
|
||||
methods with :func:`~asgiref.sync.async_to_sync` *inside* of them instead::
|
||||
|
||||
from asgiref.sync import async_to_sync
|
||||
from django.test import TestCase
|
||||
|
||||
class MyTests(TestCase):
|
||||
|
||||
@mock.patch(...)
|
||||
@async_to_sync
|
||||
def test_my_thing(self):
|
||||
...
|
||||
|
||||
.. _topics-testing-email:
|
||||
|
||||
Email services
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue