django - pytest django:无法在夹具拆解中访问数据库
问题描述
我需要在使用后显式删除一个夹具。我知道 pytest-django 默认情况下会在拆卸时丢弃所有对象,但在这种特殊情况下,我需要手动完成。然而,虽然我的测试被标记为pytest.mark.django_db
,我可以创建一个夹具,但无法在yield
一行之后删除它:
import pytest
from tgapps.models import TelegramApp
@pytest.fixture(scope='module')
def some_fixture():
app = TelegramApp.objects.create(
session_data=b'\xa2\x8f#',
app_owner_phone=79856235474,
app_id=182475,
app_hash='aad9ab4384fea1af0342b77b606d13b0'
)
yield app
print('deleting object...')
app.delete()
class TestTelegramServiceObject(object):
@pytest.mark.django_db
def test1(self, some_fixture):
print('Fixture created:')
print(some_fixture)
这是我的测试输出:
============================= test session starts ==============================
platform darwin -- Python 3.6.4, pytest-3.4.0, py-1.5.2, pluggy-0.6.0
Django settings: inviter.settings.staging (from ini file)
rootdir: /Users/1111/_projects/fasttrack/inviter, inifile: pytest.ini
plugins: mock-1.7.1, dotenv-0.1.0, django-3.1.2
collected 1 item
test_example.py E.Fixture created:
<79856235474 - 182475>
deleting object...
tests/api/test_example.py:25 (TestTelegramServiceObject.test1)
@pytest.fixture(scope='module')
def some_fixture():
app = TelegramApp.objects.create(
session_data=b'\xa2\x8f#',
app_owner_phone=79856235474,
app_id=182475,
app_hash='aad9ab4384fea1af0342b77b606d13b0'
)
yield app
print('deleting object...')
> app.delete()
test_example.py:21:
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
/Users/1111/.virtualenvs/inviter-WB5rPISo/lib/python3.6/site-packages/django/db/models/base.py:890: in delete
collector.collect([self], keep_parents=keep_parents)
/Users/1111/.virtualenvs/inviter-WB5rPISo/lib/python3.6/site-packages/django/db/models/deletion.py:221: in collect
elif sub_objs:
/Users/1111/.virtualenvs/inviter-WB5rPISo/lib/python3.6/site-packages/django/db/models/query.py:276: in __bool__
self._fetch_all()
/Users/1111/.virtualenvs/inviter-WB5rPISo/lib/python3.6/site-packages/django/db/models/query.py:1179: in _fetch_all
self._result_cache = list(self._iterable_class(self))
/Users/1111/.virtualenvs/inviter-WB5rPISo/lib/python3.6/site-packages/django/db/models/query.py:53: in __iter__
results = compiler.execute_sql(chunked_fetch=self.chunked_fetch, chunk_size=self.chunk_size)
/Users/1111/.virtualenvs/inviter-WB5rPISo/lib/python3.6/site-packages/django/db/models/sql/compiler.py:1062: in execute_sql
cursor = self.connection.cursor()
/Users/1111/.virtualenvs/inviter-WB5rPISo/lib/python3.6/site-packages/django/db/backends/base/base.py:255: in cursor
return self._cursor()
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
self = <django.db.backends.postgresql.base.DatabaseWrapper object at 0x1048bf080>
name = None
def _cursor(self, name=None):
> self.ensure_connection()
E Failed: Database access not allowed, use the "django_db" mark, or the "db" or "transactional_db" fixtures to enable it.
为什么是这样?以及如何在夹具拆卸时启用 DB 评估?
解决方案
Andreas Profous 提到的db
夹具是功能范围的,因此在这里不起作用。
你需要做的是:
@pytest.fixture(scope='module')
def some_fixture(django_db_setup, django_db_blocker):
with django_db_blocker.unblock():
app = TelegramApp.objects.create(
session_data=b'\xa2\x8f#',
app_owner_phone=79856235474,
app_id=182475,
app_hash='aad9ab4384fea1af0342b77b606d13b0'
)
yield app
with django_db_blocker.unblock():
print('deleting object...')
app.delete()
django_db_setup
确保测试数据库已设置(并准备好)以添加其他记录。django_db_blocker
是db
夹具用来允许功能范围修改的东西。它是函数作用域的原因是它会表现出TestCase
方法在默认 unittest 框架中的行为方式,其中记录在每次测试后回滚。这是一件好事,它确保在一个测试中修改记录不会改变其他测试的结果。
因此,在创建非功能范围的固定装置时要非常小心,因为默认情况下您的修改不会被包装在事务中并回滚。使用django_db_blocker
可以挂钩到django_db_blocker.unblock()
从修改数据库中删除块的方法。这在您的非功能范围固定装置中是必需的。
推荐阅读
- javascript - JavaScript/jQuery:将多个参数传递给 API 中的 POST 请求
- github - 无法将来自 IntelliJ 的 GitHub 与未知主机的消息连接
- c# - 我应该如何在 .NETStandard 1.3 中添加 System.Data.Table 引用?
- html - 背景图像显示图像的特定部分
- .net - .NET - 确保跨线程事件处理在处理表单后不会引发异常
- python-3.x - 如何更新,然后用 Python 和 DBUtils PersistentDB 选择更新的数据?
- angular - 传单 divIcon 未以角度显示在地图上
- json - 无法从 DynamoDB 数据库中为 Alexa 技能正确检索读取的 JSON 数据
- php - php中注册页面的数据库中的值未更新
- php - Codeigniter 复杂的 MySQL 查询