test: update Phase 2 tests for ASR provider abstraction

Update TestTranscribeFull to use async/await and patch the moved OpenAI import (now in asr_providers.py). Set ASR_PROVIDER=dashscope in test fixtures to ensure tests don't pick up the real .env ASR_PROVIDER value. All 19 Phase 2 + 7 integration tests pass.

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
Woody 2026-05-19 09:48:58 +08:00
parent 733824c177
commit 6928fff8ff
3 changed files with 22 additions and 13 deletions

View File

@ -27,6 +27,7 @@ def video_client(tmp_path, monkeypatch):
upload_dir.mkdir()
monkeypatch.setenv("VIDEO_UPLOAD_DIR", str(upload_dir))
monkeypatch.setenv("MAX_VIDEO_SIZE_MB", "50")
monkeypatch.setenv("ASR_PROVIDER", "dashscope")
monkeypatch.setenv("DASHSCOPE_API_KEY", "sk-test-key")
from app.core.config import get_settings
@ -49,7 +50,7 @@ def _upload_video(client, filename="test.mp4", content=b"\x00" * 1024):
class TestUploadTranscribeFlow:
"""Full upload → transcribe with mocked ASR and real file I/O."""
@patch("app.services.asr_client.OpenAI")
@patch("app.services.asr_providers.OpenAI")
@patch("app.services.video_service.asyncio.create_subprocess_exec")
def test_upload_then_transcribe(self, mock_subprocess, mock_openai_cls, video_client):
"""Upload video → extract audio (mocked ffmpeg) → transcribe (mocked ASR) → verify response."""
@ -93,7 +94,7 @@ class TestUploadTranscribeFlow:
wav_path = upload_dir / f"{video_id}_audio.wav"
assert not wav_path.exists(), "Temp WAV file should be cleaned up after transcription"
@patch("app.services.asr_client.OpenAI")
@patch("app.services.asr_providers.OpenAI")
@patch("app.services.video_service.asyncio.create_subprocess_exec")
def test_upload_transcribe_custom_language(self, mock_subprocess, mock_openai_cls, video_client):
"""Transcribe with language=en should pass it through."""

View File

@ -123,10 +123,12 @@ class TestToTraditional:
class TestTranscribeFull:
def test_returns_traditional_chinese_text(self, monkeypatch):
@pytest.mark.asyncio
async def test_returns_traditional_chinese_text(self, monkeypatch):
from app.services.asr_client import ASRClient
settings = MagicMock()
settings.asr_provider = "dashscope"
settings.dashscope_api_key = "sk-test-key"
settings.asr_model_name = "qwen3-asr-flash"
@ -139,8 +141,8 @@ class TestTranscribeFull:
mock_openai_client = MagicMock()
mock_openai_client.chat.completions.create.return_value = mock_resp
with patch("app.services.asr_client.OpenAI", return_value=mock_openai_client):
result = client.transcribe_full(b"fake-audio-bytes", language="yue")
with patch("app.services.asr_providers.OpenAI", return_value=mock_openai_client):
result = await client.transcribe_full(b"fake-audio-bytes", language="yue")
assert result == "測試結果"
mock_openai_client.chat.completions.create.assert_called_once()
@ -148,10 +150,12 @@ class TestTranscribeFull:
assert call_kwargs.kwargs["model"] == "qwen3-asr-flash"
assert call_kwargs.kwargs["extra_body"]["asr_options"]["language"] == "yue"
def test_uses_correct_api_endpoint(self, monkeypatch):
@pytest.mark.asyncio
async def test_uses_correct_api_endpoint(self, monkeypatch):
from app.services.asr_client import ASRClient
settings = MagicMock()
settings.asr_provider = "dashscope"
settings.dashscope_api_key = "sk-test-key"
settings.asr_model_name = "qwen3-asr-flash"
@ -164,17 +168,19 @@ class TestTranscribeFull:
mock_openai_client = MagicMock()
mock_openai_client.chat.completions.create.return_value = mock_resp
with patch("app.services.asr_client.OpenAI", return_value=mock_openai_client) as mock_openai_cls:
client.transcribe_full(b"audio", language="yue")
with patch("app.services.asr_providers.OpenAI", return_value=mock_openai_client) as mock_openai_cls:
await client.transcribe_full(b"audio", language="yue")
mock_openai_cls.assert_called_once_with(
api_key="sk-test-key",
base_url="https://dashscope-intl.aliyuncs.com/compatible-mode/v1",
)
def test_auto_language_omits_language_param(self, monkeypatch):
@pytest.mark.asyncio
async def test_auto_language_omits_language_param(self, monkeypatch):
from app.services.asr_client import ASRClient
settings = MagicMock()
settings.asr_provider = "dashscope"
settings.dashscope_api_key = "sk-test-key"
settings.asr_model_name = "qwen3-asr-flash"
@ -187,8 +193,8 @@ class TestTranscribeFull:
mock_openai_client = MagicMock()
mock_openai_client.chat.completions.create.return_value = mock_resp
with patch("app.services.asr_client.OpenAI", return_value=mock_openai_client):
client.transcribe_full(b"audio", language="auto")
with patch("app.services.asr_providers.OpenAI", return_value=mock_openai_client):
await client.transcribe_full(b"audio", language="auto")
call_kwargs = mock_openai_client.chat.completions.create.call_args
assert call_kwargs.kwargs.get("extra_body") is None

View File

@ -23,6 +23,7 @@ def video_client(tmp_path, monkeypatch):
upload_dir.mkdir()
monkeypatch.setenv("VIDEO_UPLOAD_DIR", str(upload_dir))
monkeypatch.setenv("MAX_VIDEO_SIZE_MB", "50")
monkeypatch.setenv("ASR_PROVIDER", "dashscope")
monkeypatch.setenv("DASHSCOPE_API_KEY", "sk-test-key")
from app.core.config import get_settings
@ -44,7 +45,7 @@ def _upload_video(client, filename="test.mp4", content=b"\x00" * 1024):
class TestTranscribeSuccess:
@patch("app.routers.video.VideoService.extract_audio")
@patch("app.services.asr_client.OpenAI")
@patch("app.services.asr_providers.OpenAI")
def test_transcribe_returns_response(self, mock_openai_cls, mock_extract, video_client):
"""POST transcribe should return FullTranscriptResponse."""
client, upload_dir = video_client
@ -74,7 +75,7 @@ class TestTranscribeSuccess:
assert "" in data["text"] or "" in data["text"]
@patch("app.routers.video.VideoService.extract_audio")
@patch("app.services.asr_client.OpenAI")
@patch("app.services.asr_providers.OpenAI")
def test_transcribe_custom_language(self, mock_openai_cls, mock_extract, video_client):
"""POST transcribe with language param should pass it through."""
client, upload_dir = video_client
@ -169,6 +170,7 @@ class TestTranscribeMissingApiKey:
upload_dir.mkdir()
monkeypatch.setenv("VIDEO_UPLOAD_DIR", str(upload_dir))
monkeypatch.setenv("MAX_VIDEO_SIZE_MB", "50")
monkeypatch.setenv("ASR_PROVIDER", "dashscope")
monkeypatch.setenv("DASHSCOPE_API_KEY", "")
from app.core.config import get_settings