summaryrefslogtreecommitdiff
path: root/tests/handlers
diff options
context:
space:
mode:
authorAndrew Godwin <andrew@aeracode.org>2020-02-12 15:15:00 -0700
committerMariusz Felisiak <felisiak.mariusz@gmail.com>2020-03-18 19:59:12 +0100
commitfc0fa72ff4cdbf5861a366e31cb8bbacd44da22d (patch)
treed419ce531586808b0a111664907b859cb6d22862 /tests/handlers
parent3f7e4b16bf58f99c71570ba75dc97db8265071be (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.py51
-rw-r--r--tests/handlers/urls.py2
-rw-r--r--tests/handlers/views.py10
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)