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

时间:2014-09-26 01:41:48

标签: 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()

线程打印空记录集,但是如果我将其扩展为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()

这将打印出创建的记录。

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

1 个答案:

答案 0 :(得分:4)

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

中有解释

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

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