diff options
Diffstat (limited to 'tests/async')
| -rw-r--r-- | tests/async/tests.py | 68 |
1 files changed, 67 insertions, 1 deletions
diff --git a/tests/async/tests.py b/tests/async/tests.py index be3e4e2576..1a0627a064 100644 --- a/tests/async/tests.py +++ b/tests/async/tests.py @@ -1,3 +1,4 @@ +import asyncio import os import sys from unittest import mock, skipIf @@ -5,9 +6,11 @@ from unittest import mock, skipIf from asgiref.sync import async_to_sync from django.core.cache import DEFAULT_CACHE_ALIAS, caches -from django.core.exceptions import SynchronousOnlyOperation +from django.core.exceptions import ImproperlyConfigured, SynchronousOnlyOperation +from django.http import HttpResponse from django.test import SimpleTestCase from django.utils.asyncio import async_unsafe +from django.views.generic.base import View from .models import SimpleModel @@ -72,3 +75,66 @@ class AsyncUnsafeTest(SimpleTestCase): self.dangerous_method() except SynchronousOnlyOperation: self.fail("SynchronousOnlyOperation should not be raised.") + + +class SyncView(View): + def get(self, request, *args, **kwargs): + return HttpResponse("Hello (sync) world!") + + +class AsyncView(View): + async def get(self, request, *args, **kwargs): + return HttpResponse("Hello (async) world!") + + +class ViewTests(SimpleTestCase): + def test_views_are_correctly_marked(self): + tests = [ + (SyncView, False), + (AsyncView, True), + ] + for view_cls, is_async in tests: + with self.subTest(view_cls=view_cls, is_async=is_async): + self.assertIs(view_cls.view_is_async, is_async) + callback = view_cls.as_view() + self.assertIs(asyncio.iscoroutinefunction(callback), is_async) + + def test_mixed_views_raise_error(self): + class MixedView(View): + def get(self, request, *args, **kwargs): + return HttpResponse("Hello (mixed) world!") + + async def post(self, request, *args, **kwargs): + return HttpResponse("Hello (mixed) world!") + + msg = ( + f"{MixedView.__qualname__} HTTP handlers must either be all sync or all " + "async." + ) + with self.assertRaisesMessage(ImproperlyConfigured, msg): + MixedView.as_view() + + def test_options_handler_responds_correctly(self): + tests = [ + (SyncView, False), + (AsyncView, True), + ] + for view_cls, is_coroutine in tests: + with self.subTest(view_cls=view_cls, is_coroutine=is_coroutine): + instance = view_cls() + response = instance.options(None) + self.assertIs( + asyncio.iscoroutine(response), + is_coroutine, + ) + if is_coroutine: + response = asyncio.run(response) + + self.assertIsInstance(response, HttpResponse) + + def test_base_view_class_is_sync(self): + """ + View and by extension any subclasses that don't define handlers are + sync. + """ + self.assertIs(View.view_is_async, False) |
