【问题标题】:Test isolation broken with multiple databases in Django. How to fix it?测试隔离在 Django 中被多个数据库破坏。如何解决?
【发布时间】:2016-07-11 12:54:47
【问题描述】:

Django 的 TestCase 类将每个测试包装在一个事务中并滚动 每次测试后返回该事务,以提供测试 隔离。

然而,显然,只有default 数据库中的操作在事务范围内。我有一个带有路由器的多数据库设置,该路由器将某些模型上的 ORM 调用定向到第二个数据库。这意味着在以下示例中,test2 失败:

class MyTestCase(TestCase):

    def test1(self):
        # Let's say Foo model ORM calls are routed to a different DB
        foo = Foo.objects.create(...)
        assert foo.is_ok()

    def test2(self):
        assert not Foo.objects.exists()

解决此问题的最直接方法是覆盖MyTestCase 中的tearDown 方法,并手动确保删除所有Foo 对象。但这有点烦人,因为它有点像 hack,并且数据库序列(例如自动增量列)不会被重置,例如,只有在测试套件完成并且数据库被销毁之后。

有没有办法正确解决这个问题,确保所有数据库操作默认在事务中进行,并在每次测试结束时回滚?

[更新]

这是我的路由器:

class FooRouter(object):

    def db_for_read(self, model, **hints):

        if model._meta.app_label == 'foo':
            return 'foo_db'

        return None

    def db_for_write(self, model, **hints):

        if model._meta.app_label == 'foo':
            return 'foo_db'

        return None

    def allow_migrate(self, db, app_label, model_name=None, **hints):

        if app_label == 'foo':
            return db == 'foo_db'

        return None

【问题讨论】:

  • 哼,我不知道,我不这么认为。这是一个非常基本的路由器。不过不管怎样,我加了代码,希望对你有帮助。
  • test2 失败。对不起,我不是很明确。刚刚更新了问题以更清楚。

标签: python django testing transactions


【解决方案1】:

由于不推荐使用 multi_db,您现在可以使用新属性 databases

实现对多个数据库的测试
class YourTestCase(TestCase):
   databases = '__all__'

   def test_something(self):
       pass

【讨论】:

  • multi_db 已从 Django 2.2 版本中弃用
【解决方案2】:

如果您没有使用 DB Router,您可以尝试将 multi_db = True 添加到 TestCase 以为所有数据库调用刷新

class YourTestCase(TestCase):
   multi_db = True

   def test_something(self):
       pass

Django docs

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-12-17
    • 2021-03-05
    • 1970-01-01
    • 2013-05-19
    相关资源
    最近更新 更多