Files
daily_stock_analysis/tests/test_task_service.py
mumu 0ab94a8c3e fix: support KR stock autocomplete suggestions (#1723)
* fix: support KR stock autocomplete suggestions

* fix(review-feedback-1723): 补充自动补全 JP/KR 建议渲染截图、前后对比或无法截图说明

* fix(review-feedback-1723): 补充 Web 自动补全 JP/KR 建议渲染的截图或无法截图说明

* fix(review-feedback-1723): docs/review-evidence-kr-autocomplete-ui.md 是针对本 PR

* fix(review-feedback-1723): 修正 PR 描述与当前 head 的实际改动、验证范围不一致问题

* fix(review-feedback-1723): 修正 PR 描述与当前 diff 的实质性不一致,避免合入记录误导后续维护者

* fix(review-feedback-1723): 收敛 PR 描述与实际 diff 的契约不一致,避免用户误以为裸 005930 已会解析为 005930.KS

* fix(review-feedback-1723): 把描述、验证证据和兼容性说明收敛到当前 6 个改动文件真实范围,或补齐描述中声称的后端/历史链路实现与测试

* fix(review-feedback-1723): 收敛 PR 描述与实际 diff,避免把未实现的 bare-code/历史展示能力作为本 PR 已交付内容合入

* fix(review-feedback-1723): 补上相应真实代码与测试后再审

* fix(review-feedback-1723): 补齐所声称的后端实现与测试后再评审

* fix(review-feedback-1723): PR description 与当前完整 diff 不一致:描述声称新增 bare JP/KR code

* fix(review-feedback-1723): PR 描述与当前完整 diff 不一致

* fix(review-feedback-1723): 补充 Refs 1718,方便后续追踪

* fix(review-feedback-1723): 收敛描述与验证证据

* fix: resolve JP KR bare stock codes

* fix: backfill JP KR daily analysis context

* fix(review-feedback-1723): preserve persisted phase timing

* fix: align JP KR history lookup keys

* fix(review-feedback-1723): preserve raw code for snapshot lookups

* fix(review-feedback-1723): 收敛
2026-06-20 10:39:40 +08:00

95 lines
2.8 KiB
Python

# -*- coding: utf-8 -*-
"""
Regression tests for TaskService failure handling.
"""
import os
import sys
import unittest
import threading
from types import ModuleType, SimpleNamespace
from unittest.mock import patch
from unittest.mock import MagicMock
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
from tests.litellm_stub import ensure_litellm_stub
ensure_litellm_stub()
from src.analyzer import AnalysisResult
from src.services.task_service import TaskService
def _make_failed_result(code: str) -> AnalysisResult:
return AnalysisResult(
code=code,
name=f"股票{code}",
sentiment_score=80,
trend_prediction="看多",
operation_advice="持有",
analysis_summary="解析失败",
success=False,
error_message="JSON 解析失败",
)
class _FakePipeline:
def __init__(self, *args, **kwargs):
self.args = args
self.kwargs = kwargs
def process_single_stock(self, *args, **kwargs):
return _make_failed_result(kwargs["code"])
class TestTaskService(unittest.TestCase):
def test_run_analysis_marks_failed_for_unsuccessful_result(self):
service = TaskService()
service._tasks = {}
service._tasks_lock = threading.Lock()
fake_main = ModuleType("main")
fake_main.StockAnalysisPipeline = _FakePipeline
with patch.dict("sys.modules", {"main": fake_main}), patch(
"src.config.get_config", return_value=SimpleNamespace()
):
result = service._run_analysis(code="600519", task_id="task-1")
self.assertFalse(result["success"])
self.assertEqual(result["error"], "JSON 解析失败")
task = service.get_task_status("task-1")
self.assertIsNotNone(task)
self.assertEqual(task["status"], "failed")
self.assertEqual(task["error"], "JSON 解析失败")
self.assertIsNone(task["result"])
def test_submit_analysis_resolves_bare_jp_kr_code_before_submit(self):
service = TaskService()
service._tasks = {}
service._tasks_lock = threading.Lock()
captured = {}
executor = MagicMock()
def capture_submit(*args, **kwargs):
captured["args"] = args
return "future"
executor.submit.side_effect = capture_submit
service._executor = executor
with patch("src.services.task_service.resolve_index_stock_code_for_analysis", return_value="005930.KS"):
result = service.submit_analysis("005930", report_type="simple", query_source="cli")
self.assertEqual(result["code"], "005930.KS")
self.assertIn("args", captured)
self.assertEqual(captured["args"][1], "005930.KS")
if __name__ == "__main__":
import unittest
unittest.main()