228 lines
7.0 KiB
Python
228 lines
7.0 KiB
Python
"""
|
|
用户注册 Use Case 测试
|
|
"""
|
|
|
|
from unittest.mock import Mock
|
|
|
|
import pytest
|
|
|
|
from packages.application.auth import (
|
|
RegisterUserRequest,
|
|
RegisterUserUseCase,
|
|
VerifyEmailRequest,
|
|
VerifyEmailUseCase,
|
|
)
|
|
from packages.domain.entities import User
|
|
|
|
|
|
class TestRegisterUserUseCase:
|
|
"""注册用例测试"""
|
|
|
|
@pytest.fixture
|
|
def mock_user_repo(self):
|
|
"""Mock 用户仓储"""
|
|
repo = Mock()
|
|
repo.find_by_email = Mock(return_value=None)
|
|
repo.find_by_username = Mock(return_value=None)
|
|
repo.find_by_verification_token = Mock(return_value=None)
|
|
repo.save = Mock()
|
|
return repo
|
|
|
|
@pytest.fixture
|
|
def use_case(self, mock_user_repo):
|
|
"""创建注册用例"""
|
|
email_service = Mock()
|
|
email_service.send_verification_email.return_value = (True, None)
|
|
return RegisterUserUseCase(
|
|
user_repository=mock_user_repo,
|
|
base_url="https://test.com",
|
|
email_service=email_service,
|
|
)
|
|
|
|
def test_register_user_success(self, use_case, mock_user_repo):
|
|
"""测试注册成功"""
|
|
|
|
request = RegisterUserRequest(
|
|
email="test@example.com",
|
|
password="SecurePass123",
|
|
username="testuser",
|
|
display_name="Test User",
|
|
)
|
|
|
|
response, error = use_case.execute(request)
|
|
|
|
assert error is None
|
|
assert response is not None
|
|
assert response.email == "test@example.com"
|
|
assert response.username == "testuser"
|
|
assert response.display_name == "Test User"
|
|
assert response.email_verification_sent is True
|
|
|
|
# 验证保存了用户
|
|
mock_user_repo.save.assert_called_once()
|
|
saved_user = mock_user_repo.save.call_args[0][0]
|
|
assert saved_user.email == "test@example.com"
|
|
assert saved_user.password_hash != ""
|
|
assert saved_user.email_verified is False
|
|
assert saved_user.email_verification_token is not None
|
|
|
|
def test_register_user_weak_password(self, use_case):
|
|
"""测试弱密码"""
|
|
request = RegisterUserRequest(
|
|
email="test@example.com",
|
|
password="weak",
|
|
username="testuser",
|
|
display_name="Test User",
|
|
)
|
|
|
|
response, error = use_case.execute(request)
|
|
|
|
assert response is None
|
|
assert error is not None
|
|
assert "at least 8 characters" in error
|
|
|
|
def test_register_user_email_exists(self, use_case, mock_user_repo):
|
|
"""测试邮箱已存在"""
|
|
# Mock 返回已存在的用户
|
|
existing_user = User(
|
|
id="existing-id",
|
|
email="test@example.com",
|
|
username="existing",
|
|
display_name="Existing",
|
|
)
|
|
mock_user_repo.find_by_email.return_value = existing_user
|
|
|
|
request = RegisterUserRequest(
|
|
email="test@example.com",
|
|
password="SecurePass123",
|
|
username="testuser",
|
|
display_name="Test User",
|
|
)
|
|
|
|
response, error = use_case.execute(request)
|
|
|
|
assert response is None
|
|
assert error == "Email already registered"
|
|
|
|
def test_register_user_username_taken(self, use_case, mock_user_repo):
|
|
"""测试用户名已被占用"""
|
|
existing_user = User(
|
|
id="existing-id",
|
|
email="other@example.com",
|
|
username="testuser",
|
|
display_name="Other",
|
|
)
|
|
mock_user_repo.find_by_username.return_value = existing_user
|
|
|
|
request = RegisterUserRequest(
|
|
email="test@example.com",
|
|
password="SecurePass123",
|
|
username="testuser",
|
|
display_name="Test User",
|
|
)
|
|
|
|
response, error = use_case.execute(request)
|
|
|
|
assert response is None
|
|
assert error == "Username already taken"
|
|
|
|
def test_register_user_missing_email(self, use_case):
|
|
"""测试缺少邮箱"""
|
|
request = RegisterUserRequest(
|
|
email="",
|
|
password="SecurePass123",
|
|
username="testuser",
|
|
display_name="Test User",
|
|
)
|
|
|
|
response, error = use_case.execute(request)
|
|
|
|
assert response is None
|
|
assert error == "Email is required"
|
|
|
|
def test_register_user_email_send_failure(self, use_case, mock_user_repo):
|
|
"""测试邮件发送失败(用户仍然创建)"""
|
|
use_case.email_service.send_verification_email.return_value = (
|
|
False,
|
|
"SMTP error",
|
|
)
|
|
|
|
request = RegisterUserRequest(
|
|
email="test@example.com",
|
|
password="SecurePass123",
|
|
username="testuser",
|
|
display_name="Test User",
|
|
)
|
|
|
|
response, error = use_case.execute(request)
|
|
|
|
assert error is None # 用户创建成功
|
|
assert response is not None
|
|
assert response.email_verification_sent is False # 但邮件发送失败
|
|
|
|
|
|
class TestVerifyEmailUseCase:
|
|
"""邮箱验证用例测试"""
|
|
|
|
@pytest.fixture
|
|
def mock_user_repo(self):
|
|
repo = Mock()
|
|
repo.find_by_verification_token = Mock(return_value=None)
|
|
repo.save = Mock()
|
|
return repo
|
|
|
|
@pytest.fixture
|
|
def use_case(self, mock_user_repo):
|
|
return VerifyEmailUseCase(user_repository=mock_user_repo)
|
|
|
|
def test_verify_email_success(self, use_case, mock_user_repo):
|
|
"""测试验证成功"""
|
|
user = User(
|
|
id="user-123",
|
|
email="test@example.com",
|
|
username="testuser",
|
|
display_name="Test User",
|
|
email_verified=False,
|
|
email_verification_token="valid-token",
|
|
)
|
|
mock_user_repo.find_by_verification_token.return_value = user
|
|
|
|
request = VerifyEmailRequest(token="valid-token")
|
|
success, error = use_case.execute(request)
|
|
|
|
assert success is True
|
|
assert error is None
|
|
|
|
# 验证用户状态已更新
|
|
assert user.email_verified is True
|
|
assert user.email_verification_token is None
|
|
mock_user_repo.save.assert_called_once()
|
|
|
|
def test_verify_email_invalid_token(self, use_case, mock_user_repo):
|
|
"""测试无效令牌"""
|
|
mock_user_repo.find_by_verification_token.return_value = None
|
|
|
|
request = VerifyEmailRequest(token="invalid-token")
|
|
success, error = use_case.execute(request)
|
|
|
|
assert success is False
|
|
assert error == "Invalid or expired verification token"
|
|
|
|
def test_verify_email_already_verified(self, use_case, mock_user_repo):
|
|
"""测试已验证的邮箱"""
|
|
user = User(
|
|
id="user-123",
|
|
email="test@example.com",
|
|
username="testuser",
|
|
display_name="Test User",
|
|
email_verified=True,
|
|
email_verification_token="old-token",
|
|
)
|
|
mock_user_repo.find_by_verification_token.return_value = user
|
|
|
|
request = VerifyEmailRequest(token="old-token")
|
|
success, error = use_case.execute(request)
|
|
|
|
assert success is True # 已验证也返回成功
|
|
assert error is None
|