Django 测试通过 SQLite,通过其他数据库失败

Django Tests Pass with SQLite, Fail with Other DB's

当我使用内置的 SQLite 作为我的数据库时,我的 Django 测试全部通过。但是,当我切换到内置 MySQL 和 PostgreSQL 时,它们失败了。 (所有本地数据库服务器。)

与数据库的连接足够活跃 -- 创建了数据库并应用了迁移。但是在测试服务器 returns 500 之前,测试甚至没有达到 views.py(即使在调试模式下也没有超出 "Server Error" 的额外解释)。

我将 Django 与 Django REST Framework 一起使用,并使用 REST Framework 的 RequestsClient class 进行测试。我的测试夹具是用 Factory Boy 生成的。

有什么想法吗?我有一种模糊的感觉,它与工厂男孩有关,但没有什么具体的。它在多个数据库中失败并成功构建表的事实让我怀疑它不是数据库本身。


测试的版本:

原来是因为我用的测试class。显然,尽管文档中现在没有说明,但 Django REST Framework RequestsClient class 只能与 DRF APILiveServerTestCase 一起使用。这在 SQLite 中完全有效是一个奇怪的侥幸。

Link: https://github.com/encode/django-rest-framework/issues/5801

编辑添加,这是 "weird fluke" 的原因,根据 Django documentation:

When using an in-memory SQLite database to run the tests, the same database connection will be shared by two threads in parallel: the thread in which the live server is run and the thread in which the test case is run.

从 SQLite 到 PostgreSQL,我遇到了类似的问题(不确定是否相同)。您是否使用设置方法来设置您的初始数据库对象?

示例::

def setUp(self):
   user = User.objects.create_user(username='john', password='abbeyRd', email='john@thebeatles.com')
   user.save()

我发现这在 SQLite 上运行良好,但在 PostgreSQL 上我遇到了数据库连接失败(它仍然会像你说的那样构建数据库,但不能 运行 没有连接错误的测试).

事实证明,解决方法是 运行 您的设置方法如下:

@classmethod
def setUpTestData(cls):
    user = User.objects.create_user(username='john', password='abbeyRd', email='john@thebeatles.com')
    user.save()

我不记得这个有效而另一个无效的确切原因,但它与尝试重新连接每个测试的数据库连接有关,如果你使用 setUp(self) 和如果你使用 setUpTestData(cls) 它只在实例化 class 时连接,但我可能没有完美的细节。我只知道它有效!

希望对您有所帮助,不确定它是否能解决您的确切问题,但我花了好几个小时才弄清楚,所以我希望它对您以及将来对其他人有帮助!

我没有这个问题的确切答案,但我有一个类似的问题 PostgreSQL 抱怨找不到 外键id=1。发生这种情况是因为 - 在某些测试中 - 我已经将要测试的对象硬编码为具有 id=1 的对象。这在 SQLite 上运行良好,因为 ID 是从 1 开始按顺序给出的,但是,这在 PostgreSQL 上不会发生。当我需要使用主键时,我通过使用 Model.objects.last().pkModel.objects.first().pk 或在两者之间选择另一个实例来解决它。