test(postgres): support multi-session integration tests
Why: - Code under test (auth resolution, the two-phase upload) opens more than one session per operation; the existing fixture only exposed one rolled-back session. Changes: - Add a db_sessionmaker fixture sharing one outer transaction. - Pin loop_scope="session" -- without it, a second async test against the session-scoped Postgres container fails with "Event loop is closed."
This commit is contained in:
@@ -54,7 +54,7 @@ def migrated_postgres_url(postgres_url: str) -> str:
|
||||
return postgres_url
|
||||
|
||||
|
||||
@pytest_asyncio.fixture(scope="session")
|
||||
@pytest_asyncio.fixture(scope="session", loop_scope="session")
|
||||
async def postgres_engine(migrated_postgres_url: str) -> AsyncIterator[AsyncEngine]:
|
||||
engine = create_engine(_settings_from_url(migrated_postgres_url))
|
||||
try:
|
||||
@@ -63,18 +63,36 @@ async def postgres_engine(migrated_postgres_url: str) -> AsyncIterator[AsyncEngi
|
||||
await engine.dispose()
|
||||
|
||||
|
||||
@pytest_asyncio.fixture
|
||||
async def db_session(postgres_engine: AsyncEngine) -> AsyncIterator[AsyncSession]:
|
||||
"""One session per test, bound to a rolled-back outer transaction.
|
||||
@pytest_asyncio.fixture(loop_scope="session")
|
||||
async def db_sessionmaker(
|
||||
postgres_engine: AsyncEngine,
|
||||
) -> AsyncIterator[async_sessionmaker[AsyncSession]]:
|
||||
"""A session *factory* per test, bound to a rolled-back outer transaction.
|
||||
|
||||
Isolates each test's writes (ADR-0016: isolate data per test) without
|
||||
needing a fresh container or unique keys per test.
|
||||
Every session it produces shares one connection/outer transaction, so
|
||||
writes `commit()`ed by one session are visible to the next -- needed for
|
||||
code under test that opens more than one session per operation (auth
|
||||
resolution, the ADR-0017 two-phase upload) -- while the whole test's
|
||||
writes still roll back together at teardown (ADR-0016: isolate data per
|
||||
test).
|
||||
"""
|
||||
async with postgres_engine.connect() as connection:
|
||||
outer_transaction = await connection.begin()
|
||||
sessionmaker = async_sessionmaker(
|
||||
bind=connection, expire_on_commit=False, join_transaction_mode="create_savepoint"
|
||||
)
|
||||
async with sessionmaker() as session:
|
||||
yield session
|
||||
yield sessionmaker
|
||||
await outer_transaction.rollback()
|
||||
|
||||
|
||||
@pytest_asyncio.fixture(loop_scope="session")
|
||||
async def db_session(
|
||||
db_sessionmaker: async_sessionmaker[AsyncSession],
|
||||
) -> AsyncIterator[AsyncSession]:
|
||||
"""One session per test, bound to a rolled-back outer transaction.
|
||||
|
||||
Isolates each test's writes (ADR-0016: isolate data per test) without
|
||||
needing a fresh container or unique keys per test.
|
||||
"""
|
||||
async with db_sessionmaker() as session:
|
||||
yield session
|
||||
|
||||
Reference in New Issue
Block a user