Files
xiaoxia-saas/tests/unit/test_email_service.py
CI Bot 1a57878f76
CI/CD Pipeline / Validate Code Quality And Tests (pull_request) Failing after 1m12s
CI/CD Pipeline / Unit Tests (pull_request) Failing after 2m17s
CI/CD Pipeline / Integration Tests (pull_request) Failing after 1m33s
CI/CD Pipeline / Frontend Lint (pull_request) Successful in 3m14s
CI/CD Pipeline / Build & Push Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Build Production Runtime Images (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
chore(backend): Phase 3 清理 — 未使用依赖删除 + pyflakes 警告清零 + 测试文件冗余清理
1. 未使用依赖清理:
   - 从 requirements-base.txt 移除 cryptography 和 pyOpenSSL

2. pyflakes 警告清零 (apps/ + packages/ + tests/):
   - 移除 17 处未使用的 import (F401)
   - 修复 26 处未使用的局部变量 (F841):
     * 有副作用的赋值转为裸调用
     * 无副作用的赋值直接删除
   - 修复 1 处未使用的异常变量 (F841)
   - 修复 1 处空 except 块

3. 测试文件冗余清理:
   - 删除 tests/integration/test_project_management.py (模块级 skip,测试不存在的模块)
   - 删除 tests/integration/fixtures/duplication_routes_fixed.py (未被引用)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-07-13 16:14:46 +08:00

177 lines
5.5 KiB
Python

"""
邮件服务测试
"""
from unittest.mock import MagicMock, patch
import pytest
from packages.domain.auth.email_service import EmailConfig, EmailService
class TestEmailService:
"""邮件服务测试"""
@pytest.fixture
def email_config(self):
"""创建测试邮件配置"""
return EmailConfig(
smtp_host="smtp.test.com",
smtp_port=587,
smtp_user="test@test.com",
smtp_password="test-password",
from_email="noreply@test.com",
from_name="Test Service",
use_tls=True,
)
@pytest.fixture
def email_service(self, email_config):
"""创建邮件服务实例"""
return EmailService(config=email_config)
@patch("smtplib.SMTP")
def test_send_email_success(self, mock_smtp, email_service):
"""测试发送邮件成功"""
# Mock SMTP 服务器
mock_server = MagicMock()
mock_smtp.return_value.__enter__.return_value = mock_server
success, error = email_service.send_email(
to_email="user@example.com",
subject="Test Email",
html_body="<h1>Test</h1>",
text_body="Test",
)
assert success is True
assert error is None
# 验证 SMTP 调用
mock_smtp.assert_called_once_with("smtp.test.com", 587)
mock_server.starttls.assert_called_once()
mock_server.login.assert_called_once_with("test@test.com", "test-password")
mock_server.sendmail.assert_called_once()
@patch("smtplib.SMTP")
def test_send_email_with_cc_bcc(self, mock_smtp, email_service):
"""测试发送邮件带抄送和密送"""
mock_server = MagicMock()
mock_smtp.return_value.__enter__.return_value = mock_server
success, error = email_service.send_email(
to_email="user@example.com",
subject="Test Email",
html_body="<h1>Test</h1>",
cc=["cc1@example.com", "cc2@example.com"],
bcc=["bcc@example.com"],
)
assert success is True
# 验证收件人列表包含所有人
call_args = mock_server.sendmail.call_args
recipients = call_args[0][1]
assert "user@example.com" in recipients
assert "cc1@example.com" in recipients
assert "cc2@example.com" in recipients
assert "bcc@example.com" in recipients
@patch("smtplib.SMTP")
def test_send_email_smtp_error(self, mock_smtp, email_service):
"""测试 SMTP 错误处理"""
# Mock SMTP 抛出异常
mock_smtp.side_effect = Exception("SMTP connection failed")
success, error = email_service.send_email(
to_email="user@example.com",
subject="Test",
html_body="<h1>Test</h1>",
)
assert success is False
assert error is not None
assert "SMTP connection failed" in error
@patch("smtplib.SMTP")
def test_send_verification_email(self, mock_smtp, email_service):
"""测试发送验证邮件"""
mock_server = MagicMock()
mock_smtp.return_value.__enter__.return_value = mock_server
success, error = email_service.send_verification_email(
to_email="user@example.com",
username="TestUser",
verification_url="https://example.com/verify?token=abc123",
)
assert success is True
assert error is None
# 验证发送了邮件
mock_server.sendmail.assert_called_once()
call_args = mock_server.sendmail.call_args
# 验证收件人
assert call_args[0][1] == ["user@example.com"]
@patch("smtplib.SMTP")
def test_send_password_reset_email(self, mock_smtp, email_service):
"""测试发送密码重置邮件"""
mock_server = MagicMock()
mock_smtp.return_value.__enter__.return_value = mock_server
success, error = email_service.send_password_reset_email(
to_email="user@example.com",
username="TestUser",
reset_url="https://example.com/reset?token=xyz789",
)
assert success is True
assert error is None
# 验证发送了邮件
mock_server.sendmail.assert_called_once()
call_args = mock_server.sendmail.call_args
# 验证收件人
assert call_args[0][1] == ["user@example.com"]
@patch("smtplib.SMTP")
def test_email_without_tls(self, mock_smtp):
"""测试不使用 TLS 发送邮件"""
config = EmailConfig(
smtp_host="smtp.test.com",
smtp_port=25,
smtp_user="",
smtp_password="",
from_email="test@test.com",
use_tls=False,
)
service = EmailService(config=config)
mock_server = MagicMock()
mock_smtp.return_value.__enter__.return_value = mock_server
success, error = service.send_email(
to_email="user@example.com",
subject="Test",
html_body="Test",
)
assert success is True
# 验证不调用 starttls
mock_server.starttls.assert_not_called()
# 验证不调用 login(没有用户名密码)
mock_server.login.assert_not_called()
def test_default_config(self):
"""测试默认配置"""
service = EmailService()
assert service.config.smtp_host == "smtp.gmail.com"
assert service.config.smtp_port == 587
assert service.config.use_tls is True
assert service.config.from_name == "小虾 SaaS"