diff --git a/work/tests/test_config_partial_save_merge.py b/work/tests/test_config_partial_save_merge.py index 650c345..0ffa4b5 100644 --- a/work/tests/test_config_partial_save_merge.py +++ b/work/tests/test_config_partial_save_merge.py @@ -32,6 +32,7 @@ omitted keys keep their live values while explicitly-sent keys still apply. """ from __future__ import annotations +import importlib import sys from unittest.mock import MagicMock @@ -41,8 +42,22 @@ from fastapi import FastAPI from fastapi.testclient import TestClient # Stub heavy optional deps so config_routes imports without them. +# +# Try the real import first -- sys.modules.setdefault() alone is only a +# no-op "in production where the real packages are installed" if some +# earlier-run test has already imported the real module. When this file +# collects first (test order is alphabetical, not guaranteed), setdefault() +# permanently replaces a genuinely-installed module (e.g. aiosqlite) with a +# bare MagicMock for the rest of the pytest session -- every later test's +# `await aiosqlite.connect(...)` then breaks with "MagicMock can't be used +# in 'await' expression". Only fall back to the mock when the real package +# truly isn't importable. for _mod in ("openai", "aiosqlite", "anthropic", "google", "google.genai"): - sys.modules.setdefault(_mod, MagicMock()) + if _mod not in sys.modules: + try: + importlib.import_module(_mod) + except ImportError: + sys.modules[_mod] = MagicMock() from meshai.config import ( # noqa: E402 Config, diff --git a/work/tests/test_fix_meshcore_save_and_llm_test.py b/work/tests/test_fix_meshcore_save_and_llm_test.py index c2c40a8..fe92bd4 100644 --- a/work/tests/test_fix_meshcore_save_and_llm_test.py +++ b/work/tests/test_fix_meshcore_save_and_llm_test.py @@ -12,6 +12,7 @@ Bug 2 — POST /api/config/test-llm "string indices must be integers, not 'str'" """ from __future__ import annotations +import importlib import sys from types import SimpleNamespace from unittest.mock import AsyncMock, MagicMock, patch @@ -20,9 +21,23 @@ import pytest # ----------------------------------------------------------------------- # Stub heavy optional deps so config_routes can be imported without them. +# +# Try the real import first -- sys.modules.setdefault() alone is only a +# no-op "in production where the real packages are installed" if some +# earlier-run test has already imported the real module. When this file +# collects first (test order is alphabetical, not guaranteed), setdefault() +# permanently replaces a genuinely-installed module (e.g. aiosqlite) with a +# bare MagicMock for the rest of the pytest session -- every later test's +# `await aiosqlite.connect(...)` then breaks with "MagicMock can't be used +# in 'await' expression". Only fall back to the mock when the real package +# truly isn't importable. # ----------------------------------------------------------------------- for _mod in ("openai", "aiosqlite", "anthropic", "google", "google.genai"): - sys.modules.setdefault(_mod, MagicMock()) + if _mod not in sys.modules: + try: + importlib.import_module(_mod) + except ImportError: + sys.modules[_mod] = MagicMock() # ========================================================================== diff --git a/work/tests/test_llm_scoping.py b/work/tests/test_llm_scoping.py index 9a647f0..c185c5c 100644 --- a/work/tests/test_llm_scoping.py +++ b/work/tests/test_llm_scoping.py @@ -7,6 +7,7 @@ Covers: (d) ContextConfig.max_age default is 14 days (1_209_600 seconds) """ +import importlib import sys from unittest.mock import MagicMock @@ -14,11 +15,23 @@ import pytest # --------------------------------------------------------------------------- # Stub optional heavy deps so meshai.router can be imported in this env. -# These stubs are set before any meshai.router import in this process; -# they are no-ops in production where the real packages are installed. +# +# Try the real import first -- sys.modules.setdefault() alone is only a +# no-op "in production where the real packages are installed" if some +# earlier-run test has already imported the real module. When this file +# collects first (test order is alphabetical, not guaranteed), setdefault() +# permanently replaces a genuinely-installed module (e.g. aiosqlite) with a +# bare MagicMock for the rest of the pytest session -- every later test's +# `await aiosqlite.connect(...)` then breaks with "MagicMock can't be used +# in 'await' expression". Only fall back to the mock when the real package +# truly isn't importable. # --------------------------------------------------------------------------- for _mod in ("openai", "aiosqlite", "anthropic", "google", "google.genai"): - sys.modules.setdefault(_mod, MagicMock()) + if _mod not in sys.modules: + try: + importlib.import_module(_mod) + except ImportError: + sys.modules[_mod] = MagicMock() from meshai.config import ( # noqa: E402 BotConfig,