pytest-django:fixture销毁阶段无法访问数据库的原因与解决
问题原因分析
你碰到的这个错误,核心问题是**@pytest.mark.django_db的作用范围没覆盖到fixture的销毁阶段**:
- 你的
some_fixture是scope='module'级别的,生命周期覆盖整个测试模块; - 测试方法上的
@pytest.mark.django_db只在测试方法执行期间启用数据库访问权限; - 当测试方法跑完后,
django_db的数据库上下文已经关闭,此时fixture中yield之后的销毁代码(app.delete())尝试访问数据库,就触发了"Database access not allowed"的限制。
简单说:测试方法的数据库权限只管测试本身,管不到module级fixture的收尾环节。
解决方案
最直接的处理方式是给fixture本身添加@pytest.mark.django_db装饰器,让fixture的整个生命周期(创建+销毁)都拥有数据库访问权限:
import pytest from tgapps.models import TelegramApp @pytest.fixture(scope='module') @pytest.mark.django_db # 把标记加到fixture上,覆盖全生命周期 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()
其他可选方案
如果你不想给fixture加标记,也可以在销毁阶段手动用django_db的上下文管理器临时解锁数据库访问:
import pytest from tgapps.models import TelegramApp from pytest_django.fixtures import django_db_blocker @pytest.fixture(scope='module') def some_fixture(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 print('deleting object...') with django_db_blocker.unblock(): app.delete()
不过第一种方案更简洁直观,推荐优先使用。
另外要注意:如果fixture是function级别的,测试方法上的django_db标记通常能覆盖销毁阶段,但module/class级别的fixture因为生命周期更长,必须单独给fixture配置权限。
内容的提问来源于stack exchange,提问作者kurtgn
相关产品推荐
相关产品推荐

