python - 如何通过 ATOMIC_REQUESTS 在多个数据库上使用 Django 的测试客户端?
问题描述
我在我的 中设置了两个数据库settings.py
,每个都有ATOMIC_REQUESTS
:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'lolomg',
'USER': 'lolomg',
'PASSWORD': 'password',
'HOST': 'localhost',
'PORT': '5432',
'ATOMIC_REQUESTS': True,
},
'analytics': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'analytics',
'USER': 'lolomg',
'PASSWORD': 'password',
'HOST': 'localhost',
'PORT': '5432',
'ATOMIC_REQUESTS': True,
},
}
如果我然后编写任何使用 Django 测试客户端的测试,例如
from django.test import TestCase
class TestEndpoints(TestCase):
def test_books(self):
self.client.get("api/v1/books")
我将获得如下所示的回溯和异常:
======================================================================
FAIL: test_books (lolomg.books.tests.test_api.EndpointsTests)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/home/jordi/vcs/lolomg/lolomg/books/tests/test_api.py", line 6, in test_books
resp = self.client.get(self.url)
File "/home/jordi/vcs/lolomg/lib/python3.7/site-packages/django/test/client.py", line 535, in get
response = super().get(path, data=data, secure=secure, **extra)
File "/home/jordi/vcs/lolomg/lib/python3.7/site-packages/django/test/client.py", line 347, in get
**extra,
File "/home/jordi/vcs/lolomg/lib/python3.7/site-packages/django/test/client.py", line 422, in generic
return self.request(**r)
File "/home/jordi/vcs/lolomg/lib/python3.7/site-packages/django/test/client.py", line 503, in request
raise exc_value
File "/home/jordi/vcs/lolomg/lib/python3.7/site-packages/django/core/handlers/exception.py", line 34, in inner
response = get_response(request)
File "/home/jordi/vcs/lolomg/lib/python3.7/site-packages/django/core/handlers/base.py", line 115, in _get_response
response = self.process_exception_by_middleware(e, request)
File "/home/jordi/vcs/lolomg/lib/python3.7/site-packages/django/core/handlers/base.py", line 113, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/usr/lib/python3.7/contextlib.py", line 73, in inner
with self._recreate_cm():
File "/home/jordi/vcs/lolomg/lib/python3.7/site-packages/django/db/transaction.py", line 175, in __enter__
if not connection.get_autocommit():
File "/home/jordi/vcs/lolomg/lib/python3.7/site-packages/django/db/backends/base/base.py", line 379, in get_autocommit
self.ensure_connection()
File "/home/jordi/vcs/lolomg/lib/python3.7/site-packages/django/db/backends/base/base.py", line 217, in ensure_connection
self.connect()
File "/home/jordi/vcs/lolomg/lib/python3.7/site-packages/django/test/testcases.py", line 144, in __call__
raise AssertionError(self.message)
AssertionError: Database connections to 'analytics' are not allowed in this test. Add 'analytics' to lolomg.books.tests.test_api.EndpointsTests.databases to ensure proper test isolation and silence this failure.
通过跟踪该堆栈跟踪,我们看到这种情况正在发生,因为测试客户端analytics
由于设置而试图为数据库建立事务ATOMIC_REQUESTS
。然而,从 Django 2.2 开始,default
现在必须在测试中显式启用与数据库的连接:
这很酷,但我实际上根本不想为这个测试连接到analytics
数据库。事实上,只有少数测试需要连接到该数据库,因此将这个数据库用于所有其他测试似乎是错误的。
虽然我可以databases = '__all__'
为任何使用测试客户端的测试类做这件事,但这似乎也是错误的。我只是不希望测试客户端尝试对大多数测试的分析数据库做任何事情。
那么我应该怎么做呢?我怎样才能保留每个数据库,但只为实际需要它的测试ATOMIC_REQUESTS
启用数据库?analytics
解决方案
我对 Django 2 还不是很熟悉,但似乎实现这一点的唯一方法是在测试运行器中禁用分析数据库的ATOMIC_REQUESTS设置,然后在涵盖它的测试中显式地重新打开它。
请参阅https://docs.djangoproject.com/en/2.2/topics/testing/tools/#overriding-settings
我认为这并不理想,因为您将在与代码运行不同的环境中运行测试,但我不确定是否有另一种方法,而不只是为所有测试启用所有数据库。
推荐阅读
- javascript - 创建一个新的模型矩阵 Webgl
- kubernetes - 迁移 PV 并更改 Kubernetes 上的 CPU 限制
- postgresql - Postgres 数组 - 如何插入和忽略重复项?
- r - 如何将值与 R 中的参考表相结合?
- python - Keras:如何使用 a(x)u+b(x) 之类的形式构建模型
- javascript - 运行命令 npm start 时出现错误
- node.js - 在 Node + Express 中销毁同一用户的每个会话的正确方法?
- java - 使用@Value 注解注入单个属性
- html - Drupal 8 视图 - 内嵌显示的未格式化字段列表(与预期不同)
- python - 单击 Django 中的按钮时出现 TypeError 和 AssertionError