使用@pytest.mark.django_db仍禁止数据库访问是否为错误用法?
问题说明与修复方案
错误原因
- 你的现有实现方式不合理,对
@pytest.mark.django_db装饰器的使用也属于错误用法:该装饰器仅作用于pytest测试函数或者pytest fixture,给普通工具函数添加该标记不会生效,无法为函数赋予测试数据库的访问权限。 - 核心触发错误的原因是你在模块顶层直接调用了
create_userprofile_list():pytest加载测试模块的时机远早于测试数据库初始化完成的时机,模块加载阶段没有可用的测试数据库连接,直接执行数据库操作自然会抛出权限错误。
正确实现方式
你需要复用测试数据的场景,最适配的方案是将数据生成逻辑改为pytest fixture,示例代码如下:
import pytest from django.contrib.auth import get_user_model from .models import UserProfile # scope参数可以根据需求调整:function(每个用例执行一次,默认)/module(每个测试模块执行一次)/session(整个测试会话执行一次) @pytest.fixture(scope="module") @pytest.mark.django_db def userprofile_list(): full_permissions_user, _ = get_user_model().objects.get_or_create( username="admin_testuser", email="admin_testuser@user.com", is_superuser=True, is_staff=True, ) staff_permissions_user, _ = get_user_model().objects.get_or_create( username="staff_testuser", email="staff_testuser@user.com", is_superuser=False, is_staff=True, ) user_permissions, _ = get_user_model().objects.get_or_create( username="normal_testuser", email="normal_testuser@user.com", is_superuser=False, is_staff=False, ) user_list = [full_permissions_user, staff_permissions_user, user_permissions] return [UserProfile.objects.get_or_create(user=user)[0] for user in user_list]
后续测试用例需要使用该数据时,直接将fixture作为参数传入测试函数即可:
@pytest.mark.django_db def test_your_business_logic(userprofile_list): admin_profile = userprofile_list[0] staff_profile = userprofile_list[1] normal_profile = userprofile_list[2] # 此处编写测试逻辑
额外注意事项
- 如果选择使用高范围的fixture(如module、session),要确保测试过程中不会修改fixture返回的数据,避免单个测试修改数据后影响其他测试的执行结果。
- 普通的数据库操作工具函数不需要单独加
@pytest.mark.django_db,只要调用该工具函数的测试函数或fixture添加了该标记,在测试上下文执行时就可以正常访问数据库。
内容的提问来源于stack exchange,提问作者Back2Basics
相关产品推荐
相关产品推荐

