"""集成测试:GET /jobs/:id 走真实 DB(无 DB 时跳过)。 get_sessionmaker 缓存的 async engine 绑定首个事件循环;pytest-asyncio 每个 测试用新循环,故每个 DB 测试清缓存以在当前循环上重建 engine,并在结束 dispose。 """ from __future__ import annotations from collections.abc import AsyncIterator import httpx import pytest from sqlalchemy import text from sqlalchemy.ext.asyncio import AsyncSession, async_sessionmaker from ww_db import get_sessionmaker from ww_db.models import Job @pytest.fixture async def sm() -> AsyncIterator[async_sessionmaker[AsyncSession]]: get_sessionmaker.cache_clear() maker = get_sessionmaker() try: async with maker() as probe: await probe.execute(text("select 1")) except Exception: pytest.skip("postgres not reachable") yield maker await maker.kw["bind"].dispose() get_sessionmaker.cache_clear() async def test_get_job_returns_row( client: httpx.AsyncClient, sm: async_sessionmaker[AsyncSession] ) -> None: async with sm() as s: job = Job(kind="style_learn", status="running", progress=42) s.add(job) await s.commit() job_id = job.id resp = await client.get(f"/jobs/{job_id}") assert resp.status_code == 200 body = resp.json() assert body["kind"] == "style_learn" assert body["progress"] == 42 async def test_get_missing_job_returns_envelope( client: httpx.AsyncClient, sm: async_sessionmaker[AsyncSession] ) -> None: resp = await client.get("/jobs/00000000-0000-0000-0000-000000000000") assert resp.status_code == 404 err = resp.json()["error"] assert err["code"] == "NOT_FOUND" assert err["request_id"]