【问题标题】:Testing several IntegrityErrors in the same Django unittest test case在同一个 Django unittest 测试用例中测试几个 IntegrityErrors
【发布时间】:2014-08-26 15:11:00
【问题描述】:

我正在尝试运行以下 Django 单元测试:

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.

我错过了什么?

【问题讨论】:

    标签: django unit-testing testing django-models


    【解决方案1】:

    您看到这个的原因是:

    1. 出于性能原因,TestCase 测试在事务中运行。
    2. IntegrityError 的引发将破坏当前事务(更准确地说,当前原子块),无论它是否被捕获。

    因此,在您的代码中,第一个 assertRaises 可以正常工作,但是因为引发了 IntegrityError,所以事务被破坏了。当您尝试使用下一个create() 访问数据库时,您会得到TransactionManagementError。请参阅this ticket 了解更多信息。

    有两种可能的解决方案:

    1. TransactionTestCase 继承而不是TestCase。这使用表截断而不是事务来重置数据库,因此您不会遇到此问题。
    2. 在一个新的原子块内运行每个create() 测试。您可以在工单中查看示例,并在 the docs 中查看更广泛的描述。

    【讨论】:

    • 非常有用。谢谢。
    猜你喜欢
    • 1970-01-01
    • 2017-09-06
    • 2014-02-27
    • 1970-01-01
    • 1970-01-01
    • 2021-10-20
    • 1970-01-01
    • 2023-03-28
    • 2014-08-01
    相关资源
    最近更新 更多