在 Django Rest Framework 中执行单元测试时出现 TransactionManagementError
TransactionManagementError While Executing Unittest in Django Rest Framework
我编写了一个测试,检查是否在数据库中出现重复记录时引发 IntegrityError。为了创建该场景,我发出了两次 REST API。代码如下所示:
class TestPost(APITestCase):
@classmethod
def setUpClass(cls):
super().setUpClass()
common.add_users()
def tearDown(self):
super().tearDown()
self.client.logout()
def test_duplicate_record(self):
# first time
response = self.client.post('/api/v1/trees/', dict(alias="some name", path="some path"))
# same request second time
response = self.client.post('/api/v1/trees/', dict(alias="some name", path="some path"))
self.assertEqual(response.status_code, status.HTTP_400_BAD_RREQUEST)
但是我得到这样的错误堆栈
"An error occurred in the current transaction. You can't "
django.db.transaction.TransactionManagementError: An error occurred in the current transaction. You can't execute queries until the end of the 'atomic' block.
How can I avoid this error this is certainly undesirable.
尝试从 tearDown
方法中删除 self.client.logout()
。 Django 在每次测试结束时回滚事务。您不必手动注销。
我今天遇到了这个问题,我花了一段时间才看到更大的图景,并妥善解决了它。确实,删除 self.client.logout()
可以解决问题,并且那里可能不需要,但问题出在您的观点上。
作为 TestCase
子类的测试将您的测试用例和测试包装在数据库事务(原子块)中,并且您的视图以某种方式破坏了该事务。对我来说,它吞下了一个 IntegrityError
异常。此时,事务已经中断,但 Django 并不知道,因此无法正确执行回滚。然后执行的任何查询都会导致 TransactionManagementError
.
我的解决方法是将视图代码正确地包装在另一个原子块中:
try:
with transaction.atomic(): # savepoint which will be rolled back
counter.save() # the operation which is expected to throw an IntegrityError
except IntegrityError:
pass # swallow the exception without breaking the transaction
如果您不使用 ATOMIC_REQUESTS
,这对您在生产中可能不是问题,但我仍然认为这是正确的解决方案。
我编写了一个测试,检查是否在数据库中出现重复记录时引发 IntegrityError。为了创建该场景,我发出了两次 REST API。代码如下所示:
class TestPost(APITestCase):
@classmethod
def setUpClass(cls):
super().setUpClass()
common.add_users()
def tearDown(self):
super().tearDown()
self.client.logout()
def test_duplicate_record(self):
# first time
response = self.client.post('/api/v1/trees/', dict(alias="some name", path="some path"))
# same request second time
response = self.client.post('/api/v1/trees/', dict(alias="some name", path="some path"))
self.assertEqual(response.status_code, status.HTTP_400_BAD_RREQUEST)
但是我得到这样的错误堆栈
"An error occurred in the current transaction. You can't "
django.db.transaction.TransactionManagementError: An error occurred in the current transaction. You can't execute queries until the end of the 'atomic' block.
How can I avoid this error this is certainly undesirable.
尝试从 tearDown
方法中删除 self.client.logout()
。 Django 在每次测试结束时回滚事务。您不必手动注销。
我今天遇到了这个问题,我花了一段时间才看到更大的图景,并妥善解决了它。确实,删除 self.client.logout()
可以解决问题,并且那里可能不需要,但问题出在您的观点上。
作为 TestCase
子类的测试将您的测试用例和测试包装在数据库事务(原子块)中,并且您的视图以某种方式破坏了该事务。对我来说,它吞下了一个 IntegrityError
异常。此时,事务已经中断,但 Django 并不知道,因此无法正确执行回滚。然后执行的任何查询都会导致 TransactionManagementError
.
我的解决方法是将视图代码正确地包装在另一个原子块中:
try:
with transaction.atomic(): # savepoint which will be rolled back
counter.save() # the operation which is expected to throw an IntegrityError
except IntegrityError:
pass # swallow the exception without breaking the transaction
如果您不使用 ATOMIC_REQUESTS
,这对您在生产中可能不是问题,但我仍然认为这是正确的解决方案。