test: 测试套件自隔离与全量离线化(collection 清零 + 杜绝真实网络) (#5873)

This commit is contained in:
InfinityPacer
2026-06-02 12:23:08 +08:00
committed by GitHub
parent 1c41d9f253
commit 437baec620
85 changed files with 14588 additions and 1163 deletions

View File

@@ -1,130 +1,10 @@
import asyncio
import importlib.util
import pickle
import sys
from contextlib import asynccontextmanager, contextmanager
from functools import wraps
from pathlib import Path
from threading import RLock
from types import ModuleType, SimpleNamespace
from unittest import TestCase
TMDB_MODULE_NAME = "app.modules.themoviedb.tmdbv3api.tmdb"
TMDB_FILE_PATH = Path(__file__).resolve().parents[1] / "app/modules/themoviedb/tmdbv3api/tmdb.py"
def _ensure_package(name: str) -> ModuleType:
module = sys.modules.get(name)
if module is None:
module = ModuleType(name)
module.__path__ = []
sys.modules[name] = module
return module
def _install_tmdb_test_stubs() -> None:
for package_name in [
"app",
"app.core",
"app.utils",
"app.modules",
"app.modules.themoviedb",
"app.modules.themoviedb.tmdbv3api",
]:
_ensure_package(package_name)
cache_module = ModuleType("app.core.cache")
def cached(*args, **kwargs):
def decorator(func):
if asyncio.iscoroutinefunction(func):
@wraps(func)
async def async_wrapper(*wrapper_args, **wrapper_kwargs):
return await func(*wrapper_args, **wrapper_kwargs)
return async_wrapper
@wraps(func)
def wrapper(*wrapper_args, **wrapper_kwargs):
return func(*wrapper_args, **wrapper_kwargs)
return wrapper
return decorator
@contextmanager
def fresh(*args, **kwargs):
yield
@asynccontextmanager
async def async_fresh(*args, **kwargs):
yield
cache_module.cached = cached
cache_module.fresh = fresh
cache_module.async_fresh = async_fresh
sys.modules[cache_module.__name__] = cache_module
config_module = ModuleType("app.core.config")
config_module.settings = SimpleNamespace(
TMDB_API_KEY="dummy-key",
TMDB_LOCALE="en-US",
PROXY=None,
TMDB_API_DOMAIN="example.com",
NORMAL_USER_AGENT="MoviePilot-Test-UA",
CONF=SimpleNamespace(tmdb=8, meta=60),
)
sys.modules[config_module.__name__] = config_module
http_module = ModuleType("app.utils.http")
class RequestUtils:
def __init__(self, *args, **kwargs):
pass
def get_res(self, *args, **kwargs): # pragma: no cover - 测试中会替换
raise NotImplementedError
def post_res(self, *args, **kwargs): # pragma: no cover - 测试中会替换
raise NotImplementedError
class AsyncRequestUtils:
def __init__(self, *args, **kwargs):
pass
async def get_res(self, *args, **kwargs): # pragma: no cover - 测试中会替换
raise NotImplementedError
async def post_res(self, *args, **kwargs): # pragma: no cover - 测试中会替换
raise NotImplementedError
http_module.RequestUtils = RequestUtils
http_module.AsyncRequestUtils = AsyncRequestUtils
sys.modules[http_module.__name__] = http_module
exceptions_module = ModuleType("app.modules.themoviedb.tmdbv3api.exceptions")
class TMDbException(Exception):
pass
exceptions_module.TMDbException = TMDbException
sys.modules[exceptions_module.__name__] = exceptions_module
def _load_tmdb_class():
_install_tmdb_test_stubs()
sys.modules.pop(TMDB_MODULE_NAME, None)
spec = importlib.util.spec_from_file_location(TMDB_MODULE_NAME, TMDB_FILE_PATH)
module = importlib.util.module_from_spec(spec)
sys.modules[TMDB_MODULE_NAME] = module
assert spec and spec.loader
spec.loader.exec_module(module)
return module.TMDb
TMDb = _load_tmdb_class()
TMDbException = sys.modules["app.modules.themoviedb.tmdbv3api.exceptions"].TMDbException
from app.modules.themoviedb.tmdbv3api.tmdb import TMDb
from app.modules.themoviedb.tmdbv3api.exceptions import TMDbException
class _FakeResponse: