From 7959f27cd6b9269f7c861ac3cf080e8578c32028 Mon Sep 17 00:00:00 2001 From: InfinityPacer Date: Fri, 28 Aug 2026 00:14:53 +0800 Subject: [PATCH] test(sdk): cover query getters and startup injection --- tests/test_agent_lifecycle.py | 6 ++-- tests/test_sdk_queries.py | 68 +++++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+), 2 deletions(-) diff --git a/tests/test_agent_lifecycle.py b/tests/test_agent_lifecycle.py index 14a3c8167..14ef84749 100644 --- a/tests/test_agent_lifecycle.py +++ b/tests/test_agent_lifecycle.py @@ -12,11 +12,12 @@ from app.agent.orchestrator import ( AgentManagerUnavailableError, ) from app.agent.tools.base import reopen_blocking_executors +from app.application import query as query_application from app.application.messaging.agent import ( create_web_agent_background_task, shutdown_web_agent_background_tasks, ) -from app.application.query import get_configured_data_query_service +from app.sdk import queries as query_sdk from app.startup.initializers import agent as agent_initializer from app.startup.initializers import modules as modules_initializer @@ -197,13 +198,14 @@ async def test_agent_initialization_failure_does_not_stop_module_startup( check_auth = MagicMock() monkeypatch.setattr(modules_initializer, "start_frontend", start_frontend) monkeypatch.setattr(modules_initializer, "check_auth", check_auth) + monkeypatch.setattr(query_application, "_configured_data_query_service", None) try: runtime = await modules_initializer.init_modules() assert runtime.workflow.system_config() is ( modules_initializer.get_configured_system_config() ) - query_page = get_configured_data_query_service().list_subscriptions({"ids": [-1]}) + query_page = await query_sdk.async_list_subscriptions({"ids": [-1]}) assert query_page.items == [] assert query_page.total == 0 finally: diff --git a/tests/test_sdk_queries.py b/tests/test_sdk_queries.py index 33be4bff3..0c08e7fcb 100644 --- a/tests/test_sdk_queries.py +++ b/tests/test_sdk_queries.py @@ -733,6 +733,74 @@ def test_sdk_get_returns_none_for_missing_records(query_sdk): assert sdk.get_transfer_history(missing_id) is None +def test_sdk_get_projects_records_and_async_uses_executor(db, query_sdk): + """四类 getter 均返回 DTO,异步入口与同步一致且经过数据库 executor。""" + sdk, executor = query_sdk + subscribe = db.add(_subscribe("Getter subscribe", media_id="getter-subscription")) + subscribe_history = db.add( + _subscribe_history( + "Getter subscription history", + media_id="getter-subscription-history", + ) + ) + download = db.add( + _download_history( + "Getter download history", + media_id="getter-download", + path="/getter/download", + ) + ) + transfer = db.add( + _transfer_history( + "Getter transfer history", + media_id="getter-transfer", + src="/getter/src", + dest="/getter/dest", + ) + ) + caller_thread_id = threading.get_ident() + cases = ( + ( + sdk.get_subscription, + sdk.async_get_subscription, + subscribe, + SubscriptionSnapshot, + ), + ( + sdk.get_subscription_history, + sdk.async_get_subscription_history, + subscribe_history, + SubscriptionHistorySnapshot, + ), + ( + sdk.get_download_history, + sdk.async_get_download_history, + download, + DownloadHistorySnapshot, + ), + ( + sdk.get_transfer_history, + sdk.async_get_transfer_history, + transfer, + TransferHistorySnapshot, + ), + ) + + for sync_call, async_call, model, snapshot_type in cases: + sync_item = sync_call(model.id) + calls_before = executor.calls + async_item = asyncio.run(async_call(model.id)) + + assert async_item == sync_item + assert isinstance(sync_item, snapshot_type) + assert not isinstance(sync_item, type(model)) + assert sync_item.id == model.id + assert executor.calls == calls_before + 1 + + assert executor.worker_thread_ids + assert all(thread_id != caller_thread_id for thread_id in executor.worker_thread_ids) + + def test_sdk_sync_async_semantics_match_and_async_uses_executor(db, query_sdk): """四个查询门面的异步结果与同步一致,并交给 executor 线程。""" sdk, executor = query_sdk