|
2 | 2 |
|
3 | 3 | from django.db import connection, connections, transaction
|
4 | 4 | from django.test import TestCase
|
| 5 | +from django.utils.decorators import method_decorator |
5 | 6 | from django.utils.unittest import skipUnless
|
6 | 7 | from rest_framework import status
|
7 |
| -from rest_framework.exceptions import APIException |
| 8 | +from rest_framework.exceptions import APIException, PermissionDenied |
8 | 9 | from rest_framework.response import Response
|
9 | 10 | from rest_framework.test import APIRequestFactory
|
10 | 11 | from rest_framework.views import APIView
|
@@ -32,6 +33,16 @@ def post(self, request, *args, **kwargs):
|
32 | 33 | raise APIException
|
33 | 34 |
|
34 | 35 |
|
| 36 | +class NonAtomicAPIExceptionView(APIView): |
| 37 | + @method_decorator(transaction.non_atomic_requests) |
| 38 | + def dispatch(self, *args, **kwargs): |
| 39 | + return super(NonAtomicAPIExceptionView, self).dispatch(*args, **kwargs) |
| 40 | + |
| 41 | + def post(self, request, *args, **kwargs): |
| 42 | + BasicModel.objects.create() |
| 43 | + raise PermissionDenied |
| 44 | + |
| 45 | + |
35 | 46 | @skipUnless(connection.features.uses_savepoints,
|
36 | 47 | "'atomic' requires transactions and savepoints.")
|
37 | 48 | class DBTransactionTests(TestCase):
|
@@ -108,3 +119,24 @@ def test_api_exception_rollback_transaction(self):
|
108 | 119 | self.assertEqual(response.status_code,
|
109 | 120 | status.HTTP_500_INTERNAL_SERVER_ERROR)
|
110 | 121 | assert BasicModel.objects.count() == 0
|
| 122 | + |
| 123 | + |
| 124 | +@skipUnless(connection.features.uses_savepoints, |
| 125 | + "'atomic' requires transactions and savepoints.") |
| 126 | +class NonAtomicDBTransactionAPIExceptionTests(TestCase): |
| 127 | + def setUp(self): |
| 128 | + self.view = NonAtomicAPIExceptionView.as_view() |
| 129 | + connections.databases['default']['ATOMIC_REQUESTS'] = True |
| 130 | + |
| 131 | + def tearDown(self): |
| 132 | + connections.databases['default']['ATOMIC_REQUESTS'] = False |
| 133 | + |
| 134 | + def test_api_exception_rollback_transaction_non_atomic_view(self): |
| 135 | + request = factory.post('/') |
| 136 | + |
| 137 | + response = self.view(request) |
| 138 | + |
| 139 | + # without checking connection.in_atomic_block view raises 500 |
| 140 | + # due attempt to rollback without transaction |
| 141 | + self.assertEqual(response.status_code, |
| 142 | + status.HTTP_403_FORBIDDEN) |
0 commit comments