diff options
| author | Andrew Godwin <andrew@aeracode.org> | 2020-02-12 15:15:00 -0700 |
|---|---|---|
| committer | Mariusz Felisiak <felisiak.mariusz@gmail.com> | 2020-03-18 19:59:12 +0100 |
| commit | fc0fa72ff4cdbf5861a366e31cb8bbacd44da22d (patch) | |
| tree | d419ce531586808b0a111664907b859cb6d22862 /tests/handlers | |
| parent | 3f7e4b16bf58f99c71570ba75dc97db8265071be (diff) | |
Fixed #31224 -- Added support for asynchronous views and middleware.
This implements support for asynchronous views, asynchronous tests,
asynchronous middleware, and an asynchronous test client.
Diffstat (limited to 'tests/handlers')
| -rw-r--r-- | tests/handlers/tests.py | 51 | ||||
| -rw-r--r-- | tests/handlers/urls.py | 2 | ||||
| -rw-r--r-- | tests/handlers/views.py | 10 |
3 files changed, 63 insertions, 0 deletions
diff --git a/tests/handlers/tests.py b/tests/handlers/tests.py index fc7074833b..dac2d967f3 100644 --- a/tests/handlers/tests.py +++ b/tests/handlers/tests.py @@ -106,6 +106,16 @@ class TransactionsPerRequestTests(TransactionTestCase): connection.settings_dict['ATOMIC_REQUESTS'] = old_atomic_requests self.assertContains(response, 'True') + async def test_auto_transaction_async_view(self): + old_atomic_requests = connection.settings_dict['ATOMIC_REQUESTS'] + try: + connection.settings_dict['ATOMIC_REQUESTS'] = True + msg = 'You cannot use ATOMIC_REQUESTS with async views.' + with self.assertRaisesMessage(RuntimeError, msg): + await self.async_client.get('/async_regular/') + finally: + connection.settings_dict['ATOMIC_REQUESTS'] = old_atomic_requests + def test_no_auto_transaction(self): old_atomic_requests = connection.settings_dict['ATOMIC_REQUESTS'] try: @@ -157,6 +167,11 @@ def empty_middleware(get_response): class HandlerRequestTests(SimpleTestCase): request_factory = RequestFactory() + def test_async_view(self): + """Calling an async view down the normal synchronous path.""" + response = self.client.get('/async_regular/') + self.assertEqual(response.status_code, 200) + def test_suspiciousop_in_view_returns_400(self): response = self.client.get('/suspicious/') self.assertEqual(response.status_code, 400) @@ -224,3 +239,39 @@ class ScriptNameTests(SimpleTestCase): 'PATH_INFO': '/milestones/accounts/login/help', }) self.assertEqual(script_name, '/mst') + + +@override_settings(ROOT_URLCONF='handlers.urls') +class AsyncHandlerRequestTests(SimpleTestCase): + """Async variants of the normal handler request tests.""" + + async def test_sync_view(self): + """Calling a sync view down the asynchronous path.""" + response = await self.async_client.get('/regular/') + self.assertEqual(response.status_code, 200) + + async def test_async_view(self): + """Calling an async view down the asynchronous path.""" + response = await self.async_client.get('/async_regular/') + self.assertEqual(response.status_code, 200) + + async def test_suspiciousop_in_view_returns_400(self): + response = await self.async_client.get('/suspicious/') + self.assertEqual(response.status_code, 400) + + async def test_no_response(self): + msg = ( + "The view handlers.views.no_response didn't return an " + "HttpResponse object. It returned None instead." + ) + with self.assertRaisesMessage(ValueError, msg): + await self.async_client.get('/no_response_fbv/') + + async def test_unawaited_response(self): + msg = ( + "The view handlers.views.async_unawaited didn't return an " + "HttpResponse object. It returned an unawaited coroutine instead. " + "You may need to add an 'await' into your view." + ) + with self.assertRaisesMessage(ValueError, msg): + await self.async_client.get('/unawaited/') diff --git a/tests/handlers/urls.py b/tests/handlers/urls.py index b008395267..a438da55b4 100644 --- a/tests/handlers/urls.py +++ b/tests/handlers/urls.py @@ -4,6 +4,7 @@ from . import views urlpatterns = [ path('regular/', views.regular), + path('async_regular/', views.async_regular), path('no_response_fbv/', views.no_response), path('no_response_cbv/', views.NoResponse()), path('streaming/', views.streaming), @@ -12,4 +13,5 @@ urlpatterns = [ path('suspicious/', views.suspicious), path('malformed_post/', views.malformed_post), path('httpstatus_enum/', views.httpstatus_enum), + path('unawaited/', views.async_unawaited), ] diff --git a/tests/handlers/views.py b/tests/handlers/views.py index 872fd52676..9180c5e5a4 100644 --- a/tests/handlers/views.py +++ b/tests/handlers/views.py @@ -1,3 +1,4 @@ +import asyncio from http import HTTPStatus from django.core.exceptions import SuspiciousOperation @@ -44,3 +45,12 @@ def malformed_post(request): def httpstatus_enum(request): return HttpResponse(status=HTTPStatus.OK) + + +async def async_regular(request): + return HttpResponse(b'regular content') + + +async def async_unawaited(request): + """Return an unawaited coroutine (common error for async views).""" + return asyncio.sleep(0) |
