From 4c5e60e96cd9e8016d7a6ce898eefa6509fdeebf Mon Sep 17 00:00:00 2001 From: yuexia5 Date: Tue, 20 Oct 2026 11:01:51 +0800 Subject: [PATCH] test(core): stop lifecycle restart test from hanging the suite `test_restart_terminates_managers_and_starts_thread` patched `astrbot.core.core_lifecycle.threading.Thread`, and that attribute is the global `threading` module, so the patch replaced `threading.Thread` process-wide. `AstrBotCoreLifecycle.restart()` awaits `asyncio.to_thread(close_trace_store)`, and `ThreadPoolExecutor` creates its workers with `threading.Thread`. With the process-wide mock the worker was a `MagicMock` that never ran, so the submitted callable was never executed and the awaited future never completed: the test hung until the 30-minute CI job timeout. Patch the `threading` reference on the lifecycle module instead, which leaves the real `threading.Thread` and the default executor intact. The assertions on the restart thread are unchanged. --- tests/unit/test_core_lifecycle.py | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/tests/unit/test_core_lifecycle.py b/tests/unit/test_core_lifecycle.py index 058f869fd61..bc5238767f0 100644 --- a/tests/unit/test_core_lifecycle.py +++ b/tests/unit/test_core_lifecycle.py @@ -895,7 +895,12 @@ async def test_restart_terminates_managers_and_starts_thread( lifecycle.astrbot_updater = MagicMock() - with patch("astrbot.core.core_lifecycle.threading.Thread") as mock_thread: + # Patch the module reference used by the lifecycle code instead of the + # global ``threading.Thread``. ``restart()`` awaits + # ``asyncio.to_thread(...)``, whose ThreadPoolExecutor spawns its worker + # with ``threading.Thread``; a process-wide mock would make that worker + # a no-op MagicMock and hang the awaiting future forever. + with patch("astrbot.core.core_lifecycle.threading") as mock_threading: await lifecycle.restart() # Verify managers were terminated @@ -904,8 +909,8 @@ async def test_restart_terminates_managers_and_starts_thread( lifecycle.kb_manager.terminate.assert_awaited_once() # Verify thread was started - mock_thread.assert_called_once() - mock_thread.return_value.start.assert_called_once() + mock_threading.Thread.assert_called_once() + mock_threading.Thread.return_value.start.assert_called_once() class TestAstrBotCoreLifecycleLoadPipelineScheduler: