1) 客服 Agent 四份交付文档 + 构建脚手架:品牌由包装占位 XX科技 / 旧名 南方财富 统一为南方基金(热线 400-889-8899 / 官网 nffund.com),系统名改为「智能服务系统」; 同步追加 §0.4 修订记录行,工程记录行保留原占位字面以支撑硬编码扫描验收。 2) 开发文档:清理 28 份已作废/残留文档(14 份移出归档 + 14 份仓库副本), 新增《文档规整方案与开发前待决事项-2026-09-17》。 3) 客服agent 四份交付文档首次纳入本分支。
107 lines
3.7 KiB
Python
107 lines
3.7 KiB
Python
"""就绪探针(B3)单元测试:Milvus 可用/不可用/客户端缺失/探测超时。"""
|
|
|
|
import asyncio
|
|
from typing import Any
|
|
|
|
import pytest
|
|
|
|
from app.service import health_service
|
|
from app.service.health_service import HealthService
|
|
|
|
|
|
class FakeMilvusClient:
|
|
def __init__(self, *, version: Any = "pkg/v2.5.4", error: Exception | None = None,
|
|
delay: float = 0.0) -> None:
|
|
self._version = version
|
|
self._error = error
|
|
self._delay = delay
|
|
self.closed = False
|
|
|
|
async def get_server_version(self) -> Any:
|
|
if self._delay:
|
|
await asyncio.sleep(self._delay)
|
|
if self._error is not None:
|
|
raise self._error
|
|
return self._version
|
|
|
|
async def close(self) -> None:
|
|
self.closed = True
|
|
|
|
|
|
def patch_client(monkeypatch: pytest.MonkeyPatch, client: Any) -> None:
|
|
monkeypatch.setattr(health_service, "_create_milvus_client", lambda uri, token: client)
|
|
|
|
|
|
async def test_available_milvus_reports_ok(monkeypatch: pytest.MonkeyPatch) -> None:
|
|
client = FakeMilvusClient()
|
|
patch_client(monkeypatch, client)
|
|
ready, state = await HealthService()._milvus_ready()
|
|
assert (ready, state) == (True, "ok")
|
|
assert client.closed is True
|
|
|
|
|
|
@pytest.mark.parametrize("error", [ConnectionError("refused"), RuntimeError("grpc down")])
|
|
async def test_unavailable_milvus_reports_unavailable(
|
|
monkeypatch: pytest.MonkeyPatch, error: Exception
|
|
) -> None:
|
|
client = FakeMilvusClient(error=error)
|
|
patch_client(monkeypatch, client)
|
|
ready, state = await HealthService()._milvus_ready()
|
|
assert (ready, state) == (False, "unavailable")
|
|
assert client.closed is True
|
|
|
|
|
|
async def test_missing_pymilvus_reports_client_missing(monkeypatch: pytest.MonkeyPatch) -> None:
|
|
def missing(uri: str, token: str) -> Any:
|
|
raise ImportError("No module named 'pymilvus'")
|
|
|
|
monkeypatch.setattr(health_service, "_create_milvus_client", missing)
|
|
ready, state = await HealthService()._milvus_ready()
|
|
assert (ready, state) == (False, "client_missing")
|
|
|
|
|
|
async def test_probe_timeout_is_bounded(monkeypatch: pytest.MonkeyPatch) -> None:
|
|
client = FakeMilvusClient(delay=5.0)
|
|
patch_client(monkeypatch, client)
|
|
ready, state = await HealthService(milvus_timeout_seconds=0.05)._milvus_ready()
|
|
assert (ready, state) == (False, "timeout")
|
|
|
|
|
|
async def test_ready_reflects_real_milvus_probe(monkeypatch: pytest.MonkeyPatch) -> None:
|
|
client = FakeMilvusClient(error=ConnectionError("milvus stopped"))
|
|
patch_client(monkeypatch, client)
|
|
|
|
async def redis_ok(_self: HealthService) -> bool:
|
|
return True
|
|
|
|
monkeypatch.setattr(HealthService, "_redis_ready", redis_ok)
|
|
result = await HealthService().ready()
|
|
assert result["checks"]["milvus"] is False
|
|
assert result["probes"]["milvus"] == "unavailable"
|
|
assert result["status"] == "degraded"
|
|
|
|
|
|
async def test_ready_is_ready_when_all_probes_pass(monkeypatch: pytest.MonkeyPatch) -> None:
|
|
patch_client(monkeypatch, FakeMilvusClient())
|
|
|
|
async def redis_ok(_self: HealthService) -> bool:
|
|
return True
|
|
|
|
monkeypatch.setattr(HealthService, "_redis_ready", redis_ok)
|
|
result = await HealthService().ready()
|
|
assert result["checks"]["milvus"] is True
|
|
assert result["probes"]["milvus"] == "ok"
|
|
assert result["checks"]["mysql"] is True
|
|
|
|
|
|
async def test_redis_failure_marks_readiness_degraded(monkeypatch: pytest.MonkeyPatch) -> None:
|
|
async def unavailable(self: HealthService) -> bool:
|
|
return False
|
|
|
|
monkeypatch.setattr(HealthService, "_redis_ready", unavailable)
|
|
patch_client(monkeypatch, FakeMilvusClient())
|
|
service = HealthService()
|
|
result = await service.ready()
|
|
assert result["checks"]["redis"] is False
|
|
assert result["status"] == "degraded"
|