Files
ctms/backend/tests/test_app_startup.py
T
Cheng Zhou d5279b124f
Storage Persistence Guard / storage-persistence-audit (push) Has been cancelled
Client Quality Gates / Shared client and Web (push) Has been cancelled
Client Quality Gates / macOS Desktop (push) Has been cancelled
Client Quality Gates / Shared client and Web (pull_request) Has been cancelled
Client Quality Gates / macOS Desktop (pull_request) Has been cancelled
Storage Persistence Guard / storage-persistence-audit (pull_request) Has been cancelled
release(main): 同步 dev 最新候选改动
2026-07-16 17:15:50 +08:00

123 lines
2.9 KiB
Python

from contextlib import asynccontextmanager
import os
from pathlib import Path
import subprocess
import sys
from unittest.mock import AsyncMock
import pytest
from fastapi import FastAPI
from app import main
def test_db_base_registers_permission_models_for_create_all():
backend_dir = Path(__file__).resolve().parents[1]
code = """
from app.db.base_class import Base
import app.db.base
required_tables = {
"api_endpoint_permissions",
"api_endpoint_registries",
"permission_templates",
"permission_template_versions",
}
missing = sorted(required_tables - set(Base.metadata.tables))
if missing:
print(",".join(missing))
raise SystemExit(1)
"""
env = {
**os.environ,
"PYTHONDONTWRITEBYTECODE": "1",
"PYTHONPATH": str(backend_dir),
}
result = subprocess.run(
[sys.executable, "-c", code],
cwd=backend_dir,
env=env,
capture_output=True,
text=True,
check=False,
)
assert result.returncode == 0, result.stdout + result.stderr
class _DummyTask:
def __init__(self):
self.awaited = False
self.cancelled = False
def cancel(self):
self.cancelled = True
def done(self):
return False
def __await__(self):
async def _wait():
self.awaited = True
return _wait().__await__()
class _DummySession:
async def __aenter__(self):
return self
async def __aexit__(self, exc_type, exc, tb):
return False
class _DummyBegin:
async def __aenter__(self):
return self
async def __aexit__(self, exc_type, exc, tb):
return False
async def run_sync(self, fn):
return None
class _DummyEngine:
def begin(self):
return _DummyBegin()
@pytest.mark.asyncio
async def test_development_startup_does_not_seed_business_data(monkeypatch):
ensure_admin_exists = AsyncMock()
create_all = AsyncMock()
legacy_pk = AsyncMock()
scheduler_task = _DummyTask()
async def fake_scheduler(stop_event):
return None
def fake_create_task(coroutine):
coroutine.close()
return scheduler_task
@asynccontextmanager
async def fake_session_local():
yield _DummySession()
monkeypatch.setattr(main.settings, "ENV", "development")
monkeypatch.setattr(main, "ensure_admin_exists", ensure_admin_exists)
monkeypatch.setattr(main, "run_daily_lost_visit_job", fake_scheduler)
monkeypatch.setattr(main, "resolve_monitoring_server_location", AsyncMock(return_value=None))
monkeypatch.setattr(main.asyncio, "create_task", fake_create_task)
monkeypatch.setattr(main, "engine", _DummyEngine())
monkeypatch.setattr(main, "SessionLocal", fake_session_local)
monkeypatch.setattr(main, "_ensure_legacy_primary_keys", legacy_pk)
monkeypatch.setattr(main.Base.metadata, "create_all", create_all)
async with main.lifespan(FastAPI()):
pass
ensure_admin_exists.assert_awaited_once()