Files
xiaoxia-saas/tests/unit/test_login_use_case.py
T
CI Test e1efbdaf6e
CI/CD Pipeline / Validate Code Quality And Tests (push) Has been cancelled
CI/CD Pipeline / Frontend Lint (push) Has been cancelled
Deploy / Deploy Staging (push) Has been cancelled
Deploy / Build Production Runtime Images (push) Has been cancelled
Deploy / Deploy Production (push) Has been cancelled
Deploy / Production Browser E2E (push) Has been cancelled
fix: resolve circular import for password_hasher/password_validator in auth __init__
2026-06-27 21:33:51 +08:00

200 lines
5.6 KiB
Python

"""
用户登录 Use Case 测试
"""
from datetime import datetime, timezone
from unittest.mock import Mock
import pytest
from packages.application.auth import (
LoginRequest,
LoginUseCase,
LogoutRequest,
LogoutUseCase,
)
from packages.application.auth.password_hasher import password_hasher
from packages.domain.entities import User
class TestLoginUseCase:
"""登录用例测试"""
@pytest.fixture
def mock_user_repo(self):
repo = Mock()
repo.find_by_email = Mock(return_value=None)
repo.save = Mock()
return repo
@pytest.fixture
def use_case(self, mock_user_repo):
session_store = Mock()
session_store.save_session.return_value = True
return LoginUseCase(user_repository=mock_user_repo, session_store=session_store)
@pytest.fixture
def test_user(self):
"""创建测试用户"""
password_hash = password_hasher.hash_password("SecurePass123")
return User(
id="user-123",
email="test@example.com",
username="testuser",
display_name="Test User",
password_hash=password_hash,
email_verified=True,
)
def test_login_success(self, use_case, mock_user_repo, test_user):
"""测试登录成功"""
mock_user_repo.find_by_email.return_value = test_user
request = LoginRequest(
email="test@example.com",
password="SecurePass123",
device_info="Chrome/Windows",
ip_address="192.168.1.1",
)
response, error = use_case.execute(request)
assert error is None
assert response is not None
assert response.user_id == "user-123"
assert response.email == "test@example.com"
assert response.username == "testuser"
assert response.access_token != ""
assert response.refresh_token != ""
assert response.expires_in > 0
# 验证保存了 session
use_case.session_store.save_session.assert_called_once()
# 验证更新了最后登录信息
mock_user_repo.save.assert_called_once()
def test_login_invalid_email(self, use_case, mock_user_repo):
"""测试邮箱不存在"""
mock_user_repo.find_by_email.return_value = None
request = LoginRequest(
email="nonexistent@example.com",
password="SecurePass123",
)
response, error = use_case.execute(request)
assert response is None
assert error == "Invalid email or password"
def test_login_wrong_password(self, use_case, mock_user_repo, test_user):
"""测试密码错误"""
mock_user_repo.find_by_email.return_value = test_user
request = LoginRequest(
email="test@example.com",
password="WrongPassword123",
)
response, error = use_case.execute(request)
assert response is None
assert error == "Invalid email or password"
def test_login_missing_email(self, use_case):
"""测试缺少邮箱"""
request = LoginRequest(
email="",
password="SecurePass123",
)
response, error = use_case.execute(request)
assert response is None
assert error == "Email is required"
def test_login_missing_password(self, use_case, mock_user_repo, test_user):
"""测试缺少密码"""
mock_user_repo.find_by_email.return_value = test_user
request = LoginRequest(
email="test@example.com",
password="",
)
response, error = use_case.execute(request)
assert response is None
assert error == "Password is required"
class TestLogoutUseCase:
"""登出用例测试"""
@pytest.fixture
def use_case(self):
session_store = Mock()
return LogoutUseCase(session_store=session_store)
def test_logout_current_device(self, use_case):
"""测试登出当前设备"""
use_case.session_store.delete_session.return_value = True
request = LogoutRequest(
user_id="user-123",
session_id="session-abc",
logout_all_devices=False,
)
success, error = use_case.execute(request)
assert success is True
assert error is None
use_case.session_store.delete_session.assert_called_once_with("session-abc")
def test_logout_all_devices(self, use_case):
"""测试登出所有设备"""
use_case.session_store.delete_all_user_sessions.return_value = 3
request = LogoutRequest(
user_id="user-123",
logout_all_devices=True,
)
success, error = use_case.execute(request)
assert success is True
assert error is None
use_case.session_store.delete_all_user_sessions.assert_called_once_with("user-123")
def test_logout_session_not_found(self, use_case):
"""测试 session 不存在"""
use_case.session_store.delete_session.return_value = False
request = LogoutRequest(
user_id="user-123",
session_id="nonexistent",
logout_all_devices=False,
)
success, error = use_case.execute(request)
assert success is False
assert error == "Session not found"
def test_logout_missing_session_id(self, use_case):
"""测试缺少 session_id"""
request = LogoutRequest(
user_id="user-123",
session_id=None,
logout_all_devices=False,
)
success, error = use_case.execute(request)
assert success is False
assert error == "Session ID is required"