test_speech_router.py 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. import importlib.util
  2. import unittest
  3. from pathlib import Path
  4. from types import SimpleNamespace
  5. from unittest.mock import Mock, patch
  6. from fastapi import UploadFile
  7. from starlette.responses import JSONResponse
  8. SPEECH_PATH = Path(__file__).resolve().parents[1] / "routers" / "speech.py"
  9. spec = importlib.util.spec_from_file_location("speech_under_test", SPEECH_PATH)
  10. speech = importlib.util.module_from_spec(spec)
  11. spec.loader.exec_module(speech)
  12. class SpeechRouterTests(unittest.IsolatedAsyncioTestCase):
  13. def _request(self, user_id=70430):
  14. return SimpleNamespace(state=SimpleNamespace(user=SimpleNamespace(user_id=user_id)))
  15. async def test_transcribe_audio_returns_text_payload(self):
  16. upload = UploadFile(filename="sample.wav", file=None)
  17. with patch.object(
  18. speech.tencent_speech_service,
  19. "transcribe_file",
  20. Mock(return_value={"text": "桥梁施工注意事项", "request_id": "req-1"}),
  21. ):
  22. response = await speech.transcribe_audio(
  23. self._request(),
  24. file=upload,
  25. user_id="web-user",
  26. )
  27. self.assertEqual(response["statusCode"], 200)
  28. self.assertEqual(response["data"]["text"], "桥梁施工注意事项")
  29. self.assertEqual(response["data"]["request_id"], "req-1")
  30. async def test_synthesize_speech_returns_audio_response(self):
  31. with patch.object(
  32. speech.tencent_speech_service,
  33. "synthesize_text",
  34. Mock(
  35. return_value={
  36. "audio_bytes": b"fake-mp3",
  37. "content_type": "audio/mpeg",
  38. "request_id": "req-2",
  39. }
  40. ),
  41. ):
  42. response = await speech.synthesize_speech(
  43. self._request(),
  44. speech.SpeechSynthesizeRequest(text="测试播报"),
  45. )
  46. self.assertEqual(response.status_code, 200)
  47. self.assertEqual(response.media_type, "audio/mpeg")
  48. self.assertEqual(response.headers["X-Speech-Request-Id"], "req-2")
  49. async def test_synthesize_speech_returns_503_when_tencent_quota_is_exhausted(self):
  50. with patch.object(
  51. speech.tencent_speech_service,
  52. "synthesize_text",
  53. Mock(
  54. side_effect=RuntimeError(
  55. "腾讯云语音合成失败: "
  56. "[TencentCloudSDKException] code:UnsupportedOperation.PkgExhausted "
  57. "message:The resource pack allowance has been exhausted"
  58. )
  59. ),
  60. ):
  61. response = await speech.synthesize_speech(
  62. self._request(),
  63. speech.SpeechSynthesizeRequest(text="测试播报"),
  64. )
  65. self.assertIsInstance(response, JSONResponse)
  66. self.assertEqual(response.status_code, 503)
  67. self.assertIn('"statusCode":503', response.body.decode("utf-8"))
  68. self.assertIn("PkgExhausted", response.body.decode("utf-8"))
  69. if __name__ == "__main__":
  70. unittest.main()