使用django-pytest测试服务时出现User.DoesNotExist错误求助
问题排查:pytest测试Django服务时出现User.DoesNotExist错误及"No tables found"提示
问题现象
- 运行pytest测试时,控制台能看到migrate输出,且生成了
db_test.sqlite3测试数据库,但同时提示No tables found - 测试用例
authentication/tests/test_services.py::test_register_user抛出错误:users.models.User.DoesNotExist: User matching query does not exist
相关代码与配置
conftest.py内容
import os import pytest from django.core.management import call_command from rest_framework.test import APIClient from users.models import User @pytest.fixture(scope='session') def delete_db(): print("delete_db") try: os.remove("db_test.sqlite3") except Exception: pass @pytest.fixture(scope='session') def django_db_setup(delete_db, django_db_blocker): print("django_db_setup") with django_db_blocker.unblock(): call_command('sqlflush') with django_db_blocker.unblock(): call_command('migrate', '--noinput') yield @pytest.fixture(autouse=True, scope='session') def user(django_db_setup, django_db_blocker): with django_db_blocker.unblock(): user = User.objects.create( name='Test user', email='test@eaxmple.com', password='Password' ) @pytest.fixture(autouse=True, scope='session') def guest_client(): return APIClient() @pytest.fixture(autouse=True, scope='session') def user_client(guest_client, django_db_blocker): with django_db_blocker.unblock(): client = APIClient() user = User.objects.get(email='test@example.com') response = guest_client.post('/api/v1/auth/login/', data={"email": user.email, "password": "Adminqwe1,"}) token = str(response.json().get("access")) client.credentials(HTTP_AUTHORIZATION="Bearer " + token) return client
测试用例文件(authentication/tests/test_services.py)
import pytest from authentication.services import register_user @pytest.mark.django_db() def test_register_user(guest_client): data = {'email': 'test1@example.com', 'name': 'Test user', 'password': 'Adminqwe1.'} user = register_user(data=data) assert user.name == 'Test user' assert user.check_password('Admninqwe1.') is True
被测试函数(authentication/services.py)
from users.models import User def register_user(data): password = data.pop("password") user = User.objects.create(**data) user.set_password(password) user.save() return user
settings_test.py数据库配置
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': BASE_DIR / 'db_test.sqlite3', } }
pytest.ini配置
[pytest] DJANGO_SETTINGS_MODULE = config.settings_test
核心问题排查与修复
1. 邮箱拼写错误导致用户查找失败
user fixture中创建用户时,邮箱写成了test@eaxmple.com(多了一个x),但user_client fixture中查找用户用的是test@example.com,直接导致找不到用户抛出异常。
修复:
修正user fixture中的邮箱拼写:
@pytest.fixture(autouse=True, scope='session') def user(django_db_setup, django_db_blocker): with django_db_blocker.unblock(): user = User.objects.create( name='Test user', email='test@example.com', # 修正拼写错误 password='Password' )
2. django_db_setup冗余操作干扰表创建
sqlflush命令会清空数据库,但在删除旧数据库后执行migrate,该操作多余且可能干扰表初始化。建议移除:
@pytest.fixture(scope='session') def django_db_setup(delete_db, django_db_blocker): print("django_db_setup") with django_db_blocker.unblock(): call_command('migrate', '--noinput') yield
3. 测试用例断言密码拼写错误
测试用例中断言的密码Admninqwe1.与传入的Adminqwe1.不一致,会导致断言失败。
修复:
修正断言中的密码:
assert user.check_password('Adminqwe1.') is True
4. autouse=True引发的执行顺序问题
user_client和user均为autouse=True的session级fixture,可能存在执行顺序不稳定的情况。建议移除user_client的autouse=True,仅在需要的测试用例中显式调用。
5. "No tables found"提示说明
该提示是pytest-django初始化阶段的临时检测结果,后续migrate已经完成表创建,修复上述错误后,测试正常运行时该提示不会影响功能。
内容的提问来源于stack exchange,提问作者Konstantinos
相关产品推荐
相关产品推荐

