Alexander Emelyanov
Alexander Emelyanov

Reputation: 23

How to create a fixture that will validate the user in the database when testing an API in FastAPI

There is an endpoint on adding a user to the database. We check if such a user already exists in the database (db_user = await get_user_by_email(email=user.email, session=session), the session is passed there from the dependency

@user_router.post('/', response_model=ResponseDataBase)
async def register_user(user: UserCreate, session: AsyncSession = Depends(get_async_session)) -> ResponseDataBase:
    user_exist_error = Error.exist_user()
    common_error = Error.common_error()
    successfully_added = Success.successfully()

    db_user = await get_user_by_email(email=user.email, session=session)

    if not db_user:
        try:
            await create_user_in_db(user=user, session=session)
            return successfully_added

        except Exception:
            raise HTTPException(status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=common_error)
    else:
        raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=user_exist_error)

Depends:

DATABASE_URL = f'postgresql+asyncpg://{DB_USER}:{DB_PASS}@{DB_HOST}:{DB_PORT}/{DB_NAME}'


Base = declarative_base()


engine = create_async_engine(DATABASE_URL)
async_session_maker = async_sessionmaker(engine, expire_on_commit=False)


async def get_async_session() -> AsyncGenerator[AsyncSession, None]:
    async with async_session_maker() as session:
        yield session

The verification function itself:

async def get_user_by_email(email: EmailStr, session: AsyncSession):
    query = select(UserORM).where(UserORM.email == email)
    result = await session.execute(query)
    return result.scalars().first()

Everything works correctly.

conftest.py:

DATABASE_URL_TEST = f'postgresql+asyncpg://{DB_USER_TEST}:{DB_PASS_TEST}@{DB_HOST_TEST}:{DB_PORT_TEST}/{DB_NAME_TEST}'

engine_test = create_async_engine(DATABASE_URL_TEST)
async_session_maker = async_sessionmaker(engine_test, expire_on_commit=False)
Base.metadata.bind = engine_test


async def _override_get_async_session() -> AsyncGenerator[AsyncSession, None]:
    async with async_session_maker() as session:
        yield session


app.dependency_overrides[get_async_session] = _override_get_async_session


@pytest.fixture(scope='session', autouse=True)
def event_loop(request):
    """Create an instance of the default event loop for each test case."""
    try:
        loop = asyncio.get_event_loop()
    except RuntimeError:
        loop = asyncio.new_event_loop()
    yield loop
    loop.close()


@pytest.fixture(autouse=True, scope="session")
def prepare_database():
    alembic_cfg = Config("alembictest.ini")
    command.upgrade(alembic_cfg, "head")
    yield
    command.downgrade(alembic_cfg, "base")


@pytest.fixture(scope="function")  # асинхронный клиент
async def ac() -> AsyncGenerator[AsyncClient, None]:
    async with AsyncClient(app=app, base_url="http://test") as ac:
        yield ac 

test_user.py:

This is where the fixtura is used, which is where the problem arises (check_user_in_db)

async def test_register(ac: AsyncClient, check_user_in_db):
    data = {
        "username": "string10",
        "email": "[email protected]",
        "password": "string10"
    }

    response = await ac.post('/user/', json=data)
    resp_data = response.json()

    assert response.status_code == 200
    assert resp_data['status'] == 'success'
    assert resp_data['data'] == 'Данные успешно добавлены.'
    assert resp_data['detail'] is None

    user_in_db = await check_user_in_db(email=data['email'])
    assert len(user_in_db) == 1

fixtura itself

@pytest.fixture
async def check_user_in_db(session: AsyncSession = Depends(get_async_session)):
    async def get_user_by_email(email: EmailStr, session: AsyncSession = session):
        query = select(User).where(User.email == email)
        result = await session.execute(query)
        return result.scalars().first()
    return get_user_by_email

Exception: FAILED tests/test_api_user.py::test_register - AttributeError: 'Depends' object has no attribute 'execute'

Tried all sorts of options, still come up with this error. Please advise, maybe someone who has encountered this error.

Upvotes: 0

Views: 49

Answers (0)

Related Questions