我正在尝试运行以下Django unittest:
class MyModelTests(TestCase):
def test_failed_duplicate(self):
m = MyModel.objects.create(a='a', b='a')
with self.assertRaises(IntegrityError):
MyModel.objects.create(a='a', b='b')
with self.assertRaises(IntegrityError):
MyModel.objects.create(a='a', b='c')
with self.assertRaises(IntegrityError):
MyModel.objects.create(a='a', b='d')
由于违反了字段a
上的唯一性约束,有几项测试都会失败。 (我对这些断言进行了一些模糊处理,但它们都测试了a
的不同值,这些值应该失败。)
然而,在跑步时我得到:
Traceback (most recent call last):
File "...", line 21, in test_failed_duplicate
MyModel.objects.create(a='a', b='c')
TransactionManagementError: An error occurred in the current transaction. You can't execute queries until the end of the 'atomic' block.
我错过了什么?
答案 0 :(得分:23)
(啊,是的。我在一段时间后遇到了这个问题并提交了a ticket。你可能会发现讨论很有趣。)
您之所以看到这一点,是因为:
TestCase
测试在事务中运行。IntegrityError
的加注会破坏当前的交易(更准确地说,是当前的原子区块),无论是否被捕获。因此,在您的代码中,第一个assertRaises
正常工作,但由于IntegrityError
被引发,因此交易变得被破坏。当您尝试使用下一个create()
访问数据库时,您会获得TransactionManagementError
。
有两种可能的解决方案:
TransactionTestCase
而非TestCase
。这使用表截断而不是事务来重置数据库,因此您不会遇到此问题。create()
测试。您可以在故障单中查看示例,并在the docs中查看更详细的说明。