""" 认证模块单元测试 """ import pytest from httpx import AsyncClient from sqlalchemy.ext.asyncio import AsyncSession from app.services.auth_service import AuthService from app.schemas.auth import UserRegister from app.core.security import verify_password, create_password_hash from app.core.exceptions import InvalidCredentialsError, UsernameExistsError @pytest.mark.asyncio class TestAuthService: """认证服务测试类""" async def test_user_registration(self, db_session: AsyncSession, test_user_data): """测试用户注册""" # 创建认证服务 auth_service = AuthService(db_session) # 准备注册数据 register_data = UserRegister(**test_user_data) # 注册用户 user = await auth_service.create_user(register_data) # 验证用户创建成功 assert user.id is not None assert user.username == test_user_data["username"] assert user.email == test_user_data["email"] assert user.is_active is True assert user.role == "trainee" # 验证密码已加密 assert user.password_hash != test_user_data["password"] assert verify_password(test_user_data["password"], user.password_hash) async def test_duplicate_username_registration( self, db_session: AsyncSession, test_user_data ): """测试重复用户名注册""" auth_service = AuthService(db_session) # 第一次注册 register_data = UserRegister(**test_user_data) await auth_service.create_user(register_data) # 尝试使用相同用户名再次注册 with pytest.raises(UsernameExistsError): await auth_service.create_user(register_data) async def test_user_login(self, db_session: AsyncSession, test_user_data): """测试用户登录""" auth_service = AuthService(db_session) # 先注册用户 register_data = UserRegister(**test_user_data) user = await auth_service.create_user(register_data) # 测试登录 authenticated_user = await auth_service.authenticate_user( username=test_user_data["username"], password=test_user_data["password"] ) assert authenticated_user.id == user.id assert authenticated_user.username == user.username # 验证登录信息已更新 assert authenticated_user.login_count == "1" assert authenticated_user.failed_login_count == "0" assert authenticated_user.last_login is not None async def test_login_with_email(self, db_session: AsyncSession, test_user_data): """测试使用邮箱登录""" auth_service = AuthService(db_session) # 注册用户 register_data = UserRegister(**test_user_data) await auth_service.create_user(register_data) # 使用邮箱登录 user = await auth_service.authenticate_user( username=test_user_data["email"], password=test_user_data["password"] ) assert user.email == test_user_data["email"] async def test_invalid_password_login( self, db_session: AsyncSession, test_user_data ): """测试错误密码登录""" auth_service = AuthService(db_session) # 注册用户 register_data = UserRegister(**test_user_data) await auth_service.create_user(register_data) # 尝试使用错误密码登录 with pytest.raises(InvalidCredentialsError): await auth_service.authenticate_user( username=test_user_data["username"], password="WrongPassword123!" ) async def test_token_creation(self, db_session: AsyncSession, test_user_data): """测试Token创建""" auth_service = AuthService(db_session) # 注册用户 register_data = UserRegister(**test_user_data) user = await auth_service.create_user(register_data) # 创建tokens tokens = await auth_service.create_tokens_for_user(user) assert "access_token" in tokens assert "refresh_token" in tokens assert tokens["token_type"] == "bearer" assert tokens["expires_in"] > 0 @pytest.mark.asyncio class TestAuthAPI: """认证API测试类""" async def test_register_endpoint(self, client: AsyncClient, test_user_data): """测试注册端点""" response = await client.post( "/api/v1/auth/register", json=test_user_data ) assert response.status_code == 200 data = response.json() assert data["code"] == 200 assert data["message"] == "注册成功" assert "access_token" in data["data"] assert "refresh_token" in data["data"] async def test_login_endpoint(self, client: AsyncClient, test_user_data): """测试登录端点""" # 先注册 await client.post("/api/v1/auth/register", json=test_user_data) # 测试登录 response = await client.post( "/api/v1/auth/login", data={ "username": test_user_data["username"], "password": test_user_data["password"] } ) assert response.status_code == 200 data = response.json() assert data["code"] == 200 assert "access_token" in data["data"] async def test_refresh_token_endpoint( self, client: AsyncClient, test_user_data ): """测试Token刷新端点""" # 先注册并获取tokens register_response = await client.post( "/api/v1/auth/register", json=test_user_data ) tokens = register_response.json()["data"] # 刷新token response = await client.post( "/api/v1/auth/refresh", json={"refresh_token": tokens["refresh_token"]} ) assert response.status_code == 200 data = response.json() assert "access_token" in data["data"] assert data["data"]["access_token"] != tokens["access_token"] async def test_logout_endpoint(self, client: AsyncClient): """测试登出端点""" response = await client.post("/api/v1/auth/logout") assert response.status_code == 200 data = response.json() assert data["message"] == "登出成功" async def test_reset_password_request(self, client: AsyncClient): """测试重置密码请求""" response = await client.post( "/api/v1/auth/reset-password", json={"email": "test@example.com"} ) assert response.status_code == 200 data = response.json() assert "如果该邮箱已注册" in data["message"]