from __future__ import annotations import unittest from tempfile import TemporaryDirectory from unittest.mock import patch from app import create_app from app.config import Config from app.email import EmailConfigurationError, send_transactional_email class TransactionalEmailTest(unittest.TestCase): def create_test_app(self, temp_dir: str, *, configured: bool): class TestConfig(Config): TESTING = True SECRET_KEY = "test-secret" SECRET_KEY_GENERATED = False SQLALCHEMY_DATABASE_URI = f"sqlite:///{temp_dir}/test.db" ADMIN_PASSWORD = None RESEND_API_KEY = "re_test_key" if configured else "" RESEND_FROM_EMAIL = "no-reply@auth.example.com" if configured else "" return create_app(TestConfig, load_model_on_start=False) def test_send_requires_resend_configuration(self) -> None: with TemporaryDirectory() as temp_dir: app = self.create_test_app(temp_dir, configured=False) with app.app_context(), self.assertRaises(EmailConfigurationError): send_transactional_email( to="user@example.com", subject="测试", html="
测试
", ) @patch("app.email.resend.Emails.send", return_value={"id": "email_123"}) def test_send_uses_configured_sender(self, send): with TemporaryDirectory() as temp_dir: app = self.create_test_app(temp_dir, configured=True) with app.app_context(): result = send_transactional_email( to="user@example.com", subject="密码重置", html="重置链接
", ) self.assertEqual(result, {"id": "email_123"}) send.assert_called_once_with( { "from": "no-reply@auth.example.com", "to": ["user@example.com"], "subject": "密码重置", "html": "重置链接
", } ) if __name__ == "__main__": unittest.main()