mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-09-06 16:07:01 +08:00
fix(testing): configure shared plugin test runtime (#6438)
This commit is contained in:
@@ -181,7 +181,7 @@ def ensure_optional_stub(name: str, **attrs) -> None:
|
|||||||
|
|
||||||
|
|
||||||
def prepare_backend() -> None:
|
def prepare_backend() -> None:
|
||||||
"""隔离 CONFIG_DIR、补 sites 垫片、建表并加载配置快照。
|
"""隔离 CONFIG_DIR、补 sites 垫片、建表并装配测试数据库能力。
|
||||||
|
|
||||||
主程序中后端即当前包;插件仓由其 ``tests/_bootstrap.py`` shim 在 import 本模块前
|
主程序中后端即当前包;插件仓由其 ``tests/_bootstrap.py`` shim 在 import 本模块前
|
||||||
先把后端目录注入 ``sys.path``。顺序固定:先隔离 CONFIG_DIR,再补 ``app.application.site.sites`` 垫片,
|
先把后端目录注入 ``sys.path``。顺序固定:先隔离 CONFIG_DIR,再补 ``app.application.site.sites`` 垫片,
|
||||||
@@ -192,9 +192,27 @@ def prepare_backend() -> None:
|
|||||||
ensure_sites_stub()
|
ensure_sites_stub()
|
||||||
from app.startup.initializers.database import init_db
|
from app.startup.initializers.database import init_db
|
||||||
init_db()
|
init_db()
|
||||||
|
from app.db.adapters.transaction import TransactionalWriteRunner
|
||||||
|
from app.db.session import SessionFactory, async_session_scope
|
||||||
|
from app.db.uow import configure_transaction_runners
|
||||||
|
|
||||||
|
transaction_runner = TransactionalWriteRunner(
|
||||||
|
sync_session=SessionFactory,
|
||||||
|
async_session=async_session_scope,
|
||||||
|
)
|
||||||
|
configure_transaction_runners(
|
||||||
|
sync=transaction_runner.sync,
|
||||||
|
async_=transaction_runner.async_,
|
||||||
|
)
|
||||||
|
from app.application.service import configure_service_directory
|
||||||
|
|
||||||
|
# 共享引导不启动真实服务模块;需要具体服务实例的测试应在自身边界显式覆盖该目录。
|
||||||
|
configure_service_directory(
|
||||||
|
configs=lambda _config_key, _conf_type: [],
|
||||||
|
modules=lambda _module_type: [],
|
||||||
|
)
|
||||||
from app.db.oper.systemconfig import SystemConfigOper
|
from app.db.oper.systemconfig import SystemConfigOper
|
||||||
from app.db.oper.userconfig import UserConfigOper
|
from app.db.oper.userconfig import UserConfigOper
|
||||||
from app.db.session import SessionFactory
|
|
||||||
|
|
||||||
with SessionFactory() as session:
|
with SessionFactory() as session:
|
||||||
SystemConfigOper().load_snapshot(session)
|
SystemConfigOper().load_snapshot(session)
|
||||||
|
|||||||
+6
-2
@@ -13,8 +13,8 @@
|
|||||||
"runtime_to_db": [],
|
"runtime_to_db": [],
|
||||||
"workflow_to_db": []
|
"workflow_to_db": []
|
||||||
},
|
},
|
||||||
"edge_count": 6595,
|
"edge_count": 6599,
|
||||||
"edge_sha256": "b0709f6e54bf046386d5df81c54a3e65889f18473b8cc91bbe7c97010bda02dc",
|
"edge_sha256": "33b44ea7d1f05a4c76fd22c4c1b798689ac8e580099c50141fbd91345a625714",
|
||||||
"edges": [
|
"edges": [
|
||||||
"app -> app.runtime",
|
"app -> app.runtime",
|
||||||
"app -> app.runtime.compat",
|
"app -> app.runtime.compat",
|
||||||
@@ -6425,12 +6425,16 @@
|
|||||||
"app.startup.lifecycle -> app.startup.lifecycle.components",
|
"app.startup.lifecycle -> app.startup.lifecycle.components",
|
||||||
"app.testing -> app.testing.stub",
|
"app.testing -> app.testing.stub",
|
||||||
"app.testing.bootstrap -> app.application",
|
"app.testing.bootstrap -> app.application",
|
||||||
|
"app.testing.bootstrap -> app.application.service",
|
||||||
"app.testing.bootstrap -> app.application.site",
|
"app.testing.bootstrap -> app.application.site",
|
||||||
"app.testing.bootstrap -> app.db",
|
"app.testing.bootstrap -> app.db",
|
||||||
|
"app.testing.bootstrap -> app.db.adapters",
|
||||||
|
"app.testing.bootstrap -> app.db.adapters.transaction",
|
||||||
"app.testing.bootstrap -> app.db.oper",
|
"app.testing.bootstrap -> app.db.oper",
|
||||||
"app.testing.bootstrap -> app.db.oper.systemconfig",
|
"app.testing.bootstrap -> app.db.oper.systemconfig",
|
||||||
"app.testing.bootstrap -> app.db.oper.userconfig",
|
"app.testing.bootstrap -> app.db.oper.userconfig",
|
||||||
"app.testing.bootstrap -> app.db.session",
|
"app.testing.bootstrap -> app.db.session",
|
||||||
|
"app.testing.bootstrap -> app.db.uow",
|
||||||
"app.testing.bootstrap -> app.startup",
|
"app.testing.bootstrap -> app.startup",
|
||||||
"app.testing.bootstrap -> app.startup.initializers",
|
"app.testing.bootstrap -> app.startup.initializers",
|
||||||
"app.testing.bootstrap -> app.startup.initializers.cache",
|
"app.testing.bootstrap -> app.startup.initializers.cache",
|
||||||
|
|||||||
@@ -0,0 +1,45 @@
|
|||||||
|
"""共享测试引导的数据库事务能力回归测试。"""
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
from sqlalchemy import text
|
||||||
|
|
||||||
|
from app.application import service
|
||||||
|
from app.db import uow
|
||||||
|
from app.schemas.types import SystemConfigKey
|
||||||
|
from app.testing.bootstrap import prepare_backend
|
||||||
|
|
||||||
|
|
||||||
|
def test_prepare_backend_configures_sync_transaction_runner(monkeypatch):
|
||||||
|
"""插件仓只调用共享引导时,无 Session Oper 仍应获得隔离事务执行器。"""
|
||||||
|
monkeypatch.setattr(uow, "_sync_transaction_runner", None)
|
||||||
|
|
||||||
|
prepare_backend()
|
||||||
|
|
||||||
|
result = uow.run_sync_transaction(
|
||||||
|
lambda session: session.execute(text("SELECT 1")).scalar_one()
|
||||||
|
)
|
||||||
|
assert result == 1
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_prepare_backend_configures_async_transaction_runner(monkeypatch):
|
||||||
|
"""共享引导同时提供异步短事务,保持与生产组合根的装配契约一致。"""
|
||||||
|
monkeypatch.setattr(uow, "_async_transaction_runner", None)
|
||||||
|
|
||||||
|
prepare_backend()
|
||||||
|
|
||||||
|
async def select_one(session):
|
||||||
|
"""在共享引导创建的隔离异步会话中执行最小查询。"""
|
||||||
|
return (await session.execute(text("SELECT 1"))).scalar_one()
|
||||||
|
|
||||||
|
assert await uow.run_async_transaction(select_one) == 1
|
||||||
|
|
||||||
|
|
||||||
|
def test_prepare_backend_configures_empty_service_directory(monkeypatch):
|
||||||
|
"""未启动真实模块时,插件通知查询应得到确定性的空服务配置。"""
|
||||||
|
monkeypatch.setattr(service, "_config_loader", service._unconfigured_configs)
|
||||||
|
monkeypatch.setattr(service, "_module_loader", service._unconfigured_modules)
|
||||||
|
|
||||||
|
prepare_backend()
|
||||||
|
|
||||||
|
assert service.get_service_configs(SystemConfigKey.Notifications, object) == []
|
||||||
Reference in New Issue
Block a user