@@ -389,32 +389,53 @@ def _clear_token() -> None:
389389
390390
391391@pytest .fixture
392- def app ():
393- """Real app for the integration suite.
394-
395- Overrides the unit-suite ``app`` fixture (tests/conftest.py), which swaps
396- in ``FakeSession`` objects for the DB dependencies. Here we want the real
397- engines wired up by the autouse ``_per_test_db_sessions`` fixture, so this
398- just yields the actual FastAPI app untouched. The shared ``client``
399- fixture depends on ``app`` by name and picks this up for integration
400- tests. Per-test overrides (sessions, ``validate_token``) are installed and
401- torn down by their own fixtures.
392+ def app (request , task_session , osm_session ):
393+ """App fixture for everything under ``tests/integration/``.
394+
395+ This directory hosts two kinds of test that share one conftest:
396+
397+ * **Container-backed** tests (marked ``integration``) run against a real
398+ PostGIS database; their DB sessions are the real engines wired by the
399+ autouse ``_per_test_db_sessions`` fixture, so we hand back the app
400+ untouched here.
401+ * **FakeSession-backed** tests (unmarked — the CLAUDE.md data-fetcher
402+ model) run the real routes/repositories but fake the ``AsyncSession``.
403+ For those we wire the fakes in exactly like the unit-suite ``app``
404+ fixture this shadows.
405+
406+ Keying on the ``integration`` marker keeps the container machinery from
407+ leaking onto the FakeSession tests (which need no Docker).
402408 """
409+ from api .core .database import get_osm_session , get_task_session
403410 from api .main import app as fastapi_app
404411
405- return fastapi_app
412+ if request .node .get_closest_marker ("integration" ):
413+ yield fastapi_app
414+ return
415+
416+ fastapi_app .dependency_overrides [get_task_session ] = lambda : task_session
417+ fastapi_app .dependency_overrides [get_osm_session ] = lambda : osm_session
418+ yield fastapi_app
419+ fastapi_app .dependency_overrides .clear ()
406420
407421
408422@pytest .fixture (autouse = True )
409- async def _per_test_db_sessions (_pg_urls ):
423+ async def _per_test_db_sessions (request ):
424+ # Only container-backed (``integration``-marked) tests need real DB
425+ # sessions; for FakeSession tests this fixture is a no-op so they never
426+ # pull in ``_pg_urls`` (which would boot / require the testcontainer).
427+ if not request .node .get_closest_marker ("integration" ):
428+ yield
429+ return
430+
410431 from sqlalchemy .ext .asyncio import async_sessionmaker , create_async_engine
411432 from sqlalchemy .pool import NullPool
412433 from sqlmodel .ext .asyncio .session import AsyncSession
413434
414435 from api .core .database import get_osm_session , get_task_session
415436 from api .main import app
416437
417- task_url , osm_url = _pg_urls
438+ task_url , osm_url = request . getfixturevalue ( " _pg_urls" )
418439
419440 # NullPool disables connection reuse: each session checkout opens a
420441 # fresh connection on the current event loop and disposes it on
0 commit comments