pythonsqlalchemyormpytestpython-asyncio

Async SQLAlchemy in pytest fixture: greenlet_spawn has not been called


So let's assume that I try to retrieve all users for Pytest tests as a fixture:

@pytest_asyncio.fixture(scope="function")
async def test_users(db_session):
    async with db_session.begin():
        cursor = await db_session.execute(
            select(User)
        )
        return cursor.scalars().fetchall()

The thing is that when I try to access objects' attributes in another function (fixture, for example), I get an error sqlalchemy.exc.MissingGreenlet: greenlet_spawn has not been called.

@pytest_asyncio.fixture(scope="function")
async def another_fixture(test_users: List[User]):
    print(test_users[0].id) # sqlalchemy.exc.MissingGreenlet: greenlet_spawn has not been called

Do I do something wrong? I tried to use db_session.refresh() on each object, but it didn't work.

UPDATE

There is my implementation of db_session fixture:

@pytest_asyncio.fixture(scope="function")
async def db_session():
    async with get_db_engine().connect() as connection:
        async with get_db_session() as session:
            yield session
        await connection.rollback()

Solution

  • The reason why you are getting this error is that you are trying to refer to a field outside of the session. You can expunge objects from the session to be able to access them elsewhere. So you'll need to update the test_users fixture like this.

    @pytest_asyncio.fixture(scope="function")
    async def test_users(db_session):
        async with db_session.begin() as session:
            cursor = await session.execute(
                select(User)
            )
            users = cursor.scalars().fetchall()
            session.expunge_all()
            return users