"""Config Base 单元测试""" from __future__ import annotations import pytest from packages.config.base import ( SharedSettings, get_cached_settings, get_shared_settings, reload_settings_cache, ) class TestSharedSettingsDefaults: """SharedSettings 默认值测试""" @pytest.fixture(autouse=True) def clean_env(self, monkeypatch): """清除所有可能影响的环境变量,确保测的是代码默认值""" env_vars = [ "ENVIRONMENT", "DEBUG", "AUTO_CREATE_SCHEMA", "DATABASE_URL", "DATABASE_POOL_SIZE", "DATABASE_MAX_OVERFLOW", "DATABASE_POOL_TIMEOUT", "DATABASE_POOL_RECYCLE", "REDIS_URL", "CELERY_BROKER_URL", "CELERY_RESULT_BACKEND", "OSS_ENDPOINT", "OSS_ACCESS_KEY_ID", "OSS_ACCESS_KEY_SECRET", "OSS_BUCKET_NAME", "OSS_DIRECT_UPLOAD_MAX_MB", "OSS_DIRECT_UPLOAD_EXPIRE_SECONDS", "COSYVOICE_API_KEY", "COSYVOICE_BASE_URL", "COSYVOICE_MODEL", "COSYVOICE_VOICE", "COSYVOICE_SAMPLE_RATE", "COSYVOICE_FORMAT", "COSYVOICE_CLONE_MODEL", "DOUBAO_API_KEY", "DOUBAO_MODEL", "DOUBAO_BASE_URL", "DOUBAO_TIMEOUT", "DOUBAO_MAX_RETRIES", ] for var in env_vars: monkeypatch.delenv(var, raising=False) reload_settings_cache() yield reload_settings_cache() def _make_settings(self): """构造不读 env 文件的纯净 settings""" return SharedSettings(_env_file="/dev/null") def test_default_environment(self): """默认环境为 development""" s = self._make_settings() assert s.environment == "development" def test_default_debug(self): """默认开启 debug""" s = self._make_settings() assert s.debug is True def test_default_database_config(self): """数据库默认配置""" s = self._make_settings() assert "postgresql" in s.database_url assert s.database_pool_size == 20 assert s.database_max_overflow == 10 assert s.database_pool_timeout == 30 assert s.database_pool_recycle == 3600 def test_default_redis_config(self): """Redis 默认配置""" s = self._make_settings() assert s.redis_url.startswith("redis://") def test_default_celery_config(self): """Celery 默认配置""" s = self._make_settings() assert s.celery_broker_url.startswith("redis://") assert s.celery_result_backend.startswith("redis://") def test_default_oss_config(self): """OSS 默认配置""" s = self._make_settings() assert s.oss_endpoint.endswith("aliyuncs.com") assert s.oss_bucket_name == "xiaoxia-autocut" assert s.oss_direct_upload_max_mb == 2000 assert s.oss_direct_upload_expire_seconds == 900 def test_default_cosyvoice_config(self): """CosyVoice 默认配置""" s = self._make_settings() assert s.cosyvoice_model == "cosyvoice-v3-flash" assert s.cosyvoice_sample_rate == 22050 assert s.cosyvoice_format == "mp3" assert s.cosyvoice_clone_model == "voice-enrollment" def test_default_doubao_config(self): """豆包默认配置""" s = self._make_settings() assert s.doubao_timeout == 30 assert s.doubao_max_retries == 2 assert "volces.com" in s.doubao_base_url def test_default_empty_api_keys(self): """API Key 默认空字符串""" s = self._make_settings() assert s.oss_access_key_id == "" assert s.oss_access_key_secret == "" assert s.cosyvoice_api_key == "" assert s.doubao_api_key == "" def test_auto_create_schema_default(self): """auto_create_schema 默认 False""" s = self._make_settings() assert s.auto_create_schema is False class TestSettingsSingleton: """单例管理测试""" def setup_method(self): """每个测试前清空缓存""" reload_settings_cache() def teardown_method(self): """每个测试后清空缓存""" reload_settings_cache() def test_get_cached_settings_same_instance(self): """同一类两次调用返回同一实例""" s1 = get_cached_settings(SharedSettings) s2 = get_cached_settings(SharedSettings) assert s1 is s2 def test_get_shared_settings_returns_shared_settings(self): """get_shared_settings 返回 SharedSettings 实例""" s = get_shared_settings() assert isinstance(s, SharedSettings) def test_get_shared_settings_singleton(self): """get_shared_settings 是单例""" s1 = get_shared_settings() s2 = get_shared_settings() assert s1 is s2 def test_reload_settings_cache_clears(self): """reload 后获取新实例""" s1 = get_cached_settings(SharedSettings) reload_settings_cache() s2 = get_cached_settings(SharedSettings) assert s1 is not s2 def test_custom_cache_key(self): """自定义 cache_key 分开缓存""" s1 = get_cached_settings(SharedSettings, cache_key="key_a") s2 = get_cached_settings(SharedSettings, cache_key="key_b") assert s1 is not s2 # 但值相同 assert s1.database_url == s2.database_url def test_different_classes_separate_cache(self): """不同类使用不同缓存""" from packages.config.api_settings import APISettings shared = get_shared_settings() api = get_cached_settings(APISettings) assert shared is not api