Django unittest:TestCase 中的线程看不到记录,但 TransactionTestCase 中的线程可以

Jam*_*Lin 4 django unit-testing

鉴于此代码:

class ImportTest(TestCase):

    account = None

    def test_atomic(self):

        def import_task():
            print Account.objects.all()

        threads = []
        self.account = Account.objects.create(name='abc')
        for i in range(10):
            t = threading.Thread(target=import_task)
            threads.append(t)
            t.start()

        for t in threads:
            t.join()
Run Code Online (Sandbox Code Playgroud)

线程打印空记录集,但如果我将其扩展TransactionTestCase如下:

class ImportTest(TransactionTestCase):

    account = None

    def test_atomic(self):

        def import_task():
            print Account.objects.all()

        threads = []
        self.account = Account.objects.create(name='abc')
        for i in range(10):
            t = threading.Thread(target=import_task)
            threads.append(t)
            t.start()

        for t in threads:
            t.join()
Run Code Online (Sandbox Code Playgroud)

这将打印出创建的记录。

有人可以解释这种行为吗?

Kev*_*nry 7

因为TestCase在事务内部运行(这是一个旨在提高性能的实现细节),所以您不应该将它用于任何本身测试或依赖事务的事情。这在文档中进行了解释。

在这种情况下发生的事情可能取决于数据库和隔离级别,但我的猜测是:测试在一个开放事务内运行,因为您正在使用TestCase; 该事务保持打开状态,直到测试结束并回滚;线程正在创建自己的数据库连接;并且由于隔离级别,他们无法看到在仍然打开的主事务中创建的对象。

好消息是您已经找到了解决方案:使用TransactionTestCase. 测试进程将在常规自动提交模式下运行,因此create()在其他线程进行查找之前提交到数据库。

  • 救星!我希望我一小时前就发现了这个。剩下的唯一问题是线程似乎没有正确关闭其连接,因此测试数据库删除失败。 (3认同)