Files
xiaoxia-saas/tests/unit/test_audio_url_presign.py
T
CI Bot a3967c6829
CI/CD Pipeline / Validate Code Quality And Tests (pull_request) Failing after 6s
CI/CD Pipeline / Unit Tests (pull_request) Failing after 10s
CI/CD Pipeline / Frontend Lint (pull_request) Failing after 1m6s
CI/CD Pipeline / Build Production Runtime Images (pull_request) Has been skipped
CI/CD Pipeline / Build & Push Staging (Watchtower auto-deploy) (pull_request) Has been skipped
CI/CD Pipeline / Staging API Integration Tests (pull_request) Has been skipped
CI/CD Pipeline / Deploy Production (pull_request) Has been skipped
CI/CD Pipeline / Staging E2E Tests (pull_request) Has been skipped
CI/CD Pipeline / Production Browser E2E (pull_request) Has been skipped
CI/CD Pipeline / Integration Tests (pull_request) Failing after 28m22s
Phase 4 Backend P0 cleanup
1. Remove unused aiosmtplib dependency from requirements.txt
2. Remove 5 unused config items (API_PREFIX, REDIS_MAX_CONNECTION,
   JWT_SECRET_KEY_OLD, SECRET_ROTATION_DAYS, LOG_LEVEL) from config.py,
   .env.production.example, and init_production_env.sh.
   Kept ENABLE_REDIS_SESSIONS (actively used in dependencies.py).
3. Fix project permission check TODOs in test_error_scenarios.py —
   permissions are implemented, updated assertions to expect 403.
4. Merge two Storage implementations into shared package:
   - packages/shared/storage.py: merged API features (HTTPS endpoint
     fix, diagnose(), detailed logging) into SharedStorageService
   - apps/api/app/core/storage.py: thin re-export wrapper for
     backward compatibility
   - Updated test mocks to target packages.shared.storage
2026-07-13 17:45:37 +08:00

92 lines
3.3 KiB
Python
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""测试音频URL预签名逻辑。
验证所有 API 返回的音频 URL 都会经过 OSS 预签名(24小时有效期),
确保私有 bucket 下的音频文件前端可正常访问。
"""
from __future__ import annotations
from unittest.mock import MagicMock, patch
class TestAudioUrlSigner:
"""测试音频URL签名函数的行为。"""
def _make_signer(self, mock_storage):
"""构造一个签名函数(模拟 get_audio_url_signer 的逻辑)。"""
def sign_audio_url(url: str) -> str:
if not url:
return url
return mock_storage.get_download_url(url, expires_seconds=86400)
return sign_audio_url
def test_empty_url_returns_empty(self):
"""空URL直接返回,不调用签名。"""
mock_storage = MagicMock()
signer = self._make_signer(mock_storage)
result = signer("")
assert result == ""
mock_storage.get_download_url.assert_not_called()
def test_none_url_returns_none(self):
"""None URL直接返回(有些字段可能为None)。"""
mock_storage = MagicMock()
signer = self._make_signer(mock_storage)
result = signer(None) # type: ignore
assert result is None
mock_storage.get_download_url.assert_not_called()
def test_valid_url_gets_signed_24h(self):
"""有效URL会调用 storage.get_download_url,有效期24小时(86400秒)。"""
mock_storage = MagicMock()
mock_storage.get_download_url.return_value = (
"https://bucket.oss-cn-hangzhou.aliyuncs.com/audio/test.mp3?signature=xxx"
)
signer = self._make_signer(mock_storage)
result = signer("https://bucket.oss-cn-hangzhou.aliyuncs.com/audio/test.mp3")
assert "signature=xxx" in result
mock_storage.get_download_url.assert_called_once_with(
"https://bucket.oss-cn-hangzhou.aliyuncs.com/audio/test.mp3",
expires_seconds=86400,
)
def test_storage_key_format_also_works(self):
"""纯 storage key 格式也能正常签名(storage内部会处理)。"""
mock_storage = MagicMock()
mock_storage.get_download_url.return_value = "https://signed-url/audio.mp3?sig=xxx"
signer = self._make_signer(mock_storage)
result = signer("audio/test.mp3")
assert result == "https://signed-url/audio.mp3?sig=xxx"
mock_storage.get_download_url.assert_called_once_with(
"audio/test.mp3",
expires_seconds=86400,
)
def test_signer_via_dependencies_module(self):
"""通过 dependencies 模块获取 signer,验证集成正确。"""
from app.core.storage import OSSStorageService
mock_svc = MagicMock(spec=OSSStorageService)
mock_svc.get_download_url.return_value = "https://signed/a.mp3?sig=123"
# 替换全局单例(现在位于 packages.shared.storage
with patch("packages.shared.storage._storage_service", mock_svc):
from app.dependencies import get_audio_url_signer
signer = get_audio_url_signer()
result = signer("test/audio.mp3")
assert result == "https://signed/a.mp3?sig=123"
mock_svc.get_download_url.assert_called_once_with(
"test/audio.mp3",
expires_seconds=86400,
)