mirror of
https://github.com/pewdiepie-archdaemon/odysseus.git
synced 2026-06-17 02:05:22 -04:00
Scope core.* module stubs to the test, not the module (#1513)
Three test files (test_auth_regressions, test_auth_event_loop, test_null_owner_gates) install stubs for core.database / core.auth / src.endpoint_resolver at module-import time, so they outlive the file and are still present in sys.modules when later-collected test files try to import the real modules. The stubs are minimal (a handful of MagicMock attrs) so the import chain that follows fails with ImportError on the very next real import. test_companion_pairing also leaks, with a twist: its _DBStub subclass returns a MagicMock for *any* attribute including dunders, so the next test that does `from core.database import *` reads `__all__` as a MagicMock and dies with 'Item in __all__ must be str, not MagicMock'. Move the stub installation into an autouse fixture per file and register each stub with monkeypatch.setitem so sys.modules is restored to its pre-test state on teardown. Tighten _DBStub to refuse dunder names so __all__ stays undefined. _CAPTURED is cleared per test so the mint-token assertions see a fresh dict. Before: 3 test files fail at collection time (test_chat_image_routing, test_context_compactor, test_webhook_ssrf_resilience). After: 0 collection errors. 1365/1370 pass, 1 skip, 4 unrelated pre-existing failures (verified against origin/main baseline). Out of scope: test_task_scheduler_session_delivery:: test_session_delivery_survives_empty_database also fails in the full suite due to order-dependent state from a different test file. That's a separate leak with a different root cause.
This commit is contained in:
@@ -37,27 +37,36 @@ def _get_db_session():
|
||||
|
||||
# core/__init__ pulls in models/session_manager which import many ORM names from
|
||||
# core.database; under conftest's sqlalchemy stubs the real module can't load.
|
||||
# A __getattr__ module resolves ANY requested name to a MagicMock, while keeping
|
||||
# our real get_db_session/ApiToken for the mint test.
|
||||
# A __getattr__ module resolves any non-dunder name to a MagicMock, while keeping
|
||||
# our real get_db_session/ApiToken for the mint test. Dunder names (e.g. __all__)
|
||||
# are NOT auto-resolved — the next test file does `from core.database import *`,
|
||||
# which would otherwise see a MagicMock where a list-of-str is required.
|
||||
class _DBStub(types.ModuleType):
|
||||
def __getattr__(self, name): # noqa: D401
|
||||
if name.startswith("__"):
|
||||
raise AttributeError(name)
|
||||
return MagicMock()
|
||||
|
||||
|
||||
_db = _DBStub("core.database")
|
||||
_db.get_db_session = _get_db_session
|
||||
_db.ApiToken = _ApiToken
|
||||
sys.modules["core.database"] = _db # overwrite any minimal stub from a sibling test
|
||||
|
||||
for _name, _attrs in {
|
||||
"core.auth": {"AuthManager": MagicMock()},
|
||||
"src.endpoint_resolver": {"build_chat_url": (lambda u: u)},
|
||||
}.items():
|
||||
if _name not in sys.modules:
|
||||
_mm = types.ModuleType(_name)
|
||||
for _k, _v in _attrs.items():
|
||||
setattr(_mm, _k, _v)
|
||||
sys.modules[_name] = _mm
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
def _companion_pairing_stubs(monkeypatch):
|
||||
monkeypatch.setitem(sys.modules, "core.database", _db)
|
||||
for _name, _attrs in {
|
||||
"core.auth": {"AuthManager": MagicMock()},
|
||||
"src.endpoint_resolver": {"build_chat_url": (lambda u: u)},
|
||||
}.items():
|
||||
if _name not in sys.modules:
|
||||
_mm = types.ModuleType(_name)
|
||||
for _k, _v in _attrs.items():
|
||||
setattr(_mm, _k, _v)
|
||||
sys.modules[_name] = _mm
|
||||
monkeypatch.setitem(sys.modules, _name, sys.modules[_name])
|
||||
|
||||
|
||||
from fastapi import HTTPException # noqa: E402
|
||||
|
||||
|
||||
Reference in New Issue
Block a user