0

I'm testing a FastAPI service that queries a database using SQLAlchemy's async execution. However, when I mock the database query, execute().scalars().all() returns an empty list instead of the expected [1, 2, 3].

async def retrieve_relevant_docs(session: AsyncSession, query: str, top_k: int):
    results = await session.execute(select(Document.id).limit(top_k))
    print("debug results", vars(results))  # Debugging
    document_ids = list(await results.scalars())
    print("document_ids", document_ids)  # Debugging
    return document_ids
import pytest
from unittest.mock import AsyncMock

@pytest.mark.asyncio
async def test_retrieve_relevant_docs():
    mock_session = AsyncMock()
    mock_execute = AsyncMock()

    # Attempt to mock scalars() to return values
    mock_scalars_selected = AsyncMock()
    mock_scalars_selected.scalars.return_value.all.return_value = [1, 2, 3]

    mock_execute.side_effect = [mock_scalars_selected, mock_scalars_selected]
    mock_session.execute = mock_execute  # Mocking session.execute

    # Calling the function
    document_ids = await retrieve_relevant_docs(mock_session, "test query", top_k=3)
    
    # Debugging
    print("Final document_ids:", document_ids)  

    assert document_ids == [1, 2, 3]  # This fails because document_ids is []

Observed Behavior: results.scalars().all() unexpectedly returns [], even though I attempted to mock it. Debugging vars(results) shows _mock_side_effect = None, suggesting the mock isn't working as expected. Expected Behavior: document_ids should contain [1, 2, 3], matching the mocked return value

What I've Tried:

  • Explicitly setting scalars().all().return_value = [1, 2, 3].
  • Checking vars(results) for missing attributes.
  • Ensuring mock_execute.side_effect is properly assigned.
  • Calling await session.execute(...).scalars().all() instead of wrapping it in list().

Extra Debug logs:

selected_ids_result debug results {'_mock_return_value': sentinel.DEFAULT, '_mock_parent': None, '_mock_name': None, '_mock_new_name': '()', '_mock_new_parent': , '_mock_sealed': False, '_spec_class': None, '_spec_set': None, '_spec_signature': None, '_mock_methods': None, '_spec_asyncs': [], '_mock_children': {'scalars': , 'str': }, '_mock_wraps': None, '_mock_delegate': None, '_mock_called': False, '_mock_call_args': None, '_mock_call_count': 0, '_mock_call_args_list': [], '_mock_mock_calls': [call.str(), call.scalars(), call.scalars().all()], 'method_calls': [call.scalars()], '_mock_unsafe': False, '_mock_side_effect': None, '_is_coroutine': <object object at 0x0000029C06E16A30>, '_mock_await_count': 0, '_mock_await_args': None, '_mock_await_args_list': [], 'code': , 'str': } document_ids [] AssertionError: assert [] == [1, 2, 3]

What is the correct way to mock SQLAlchemy's async execution (session.execute().scalars().all()) in a FastAPI test using AsyncMock?

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.