How to mocks logging pytest in a fastapi call

Question:

i am working in a project with fastAPI

As the title says, i have an endpoint which calls a logging event when a HTTPException occurs, and when the request is called and finished

Something like this:

@router.get(
    "/chat/{chat_id}/messages/", 
    status_code=status.HTTP_200_OK,
)
async def get_messages(chat_message: GetMessageValidator = Depends(), request: Request = None):
    logging.info(request.url.path+" request started") ##LOGGING

    if chat_message.chat_id_validator(chat_message.chat_id):
        logging.error(request.url.path+settings.GET_MESSAGES_CHAT_ID_ERROR) ##LOGGING

        raise HTTPException(
            status_code=404, detail=settings.GET_MESSAGES_CHAT_ID_ERROR
        )
    logging.info(request.url.path+" request OK") ##LOGGING

    return chat_message

And i have build a test with pytest which call that endpoint, something like this:

@dataclass
class ChatMessage:
    from_user: str
    to_user: str
    chat_id: str
    body: str

@pytest.mark.asyncio()
async def test_pagination_get_messages(client: AsyncSession, 
    user_token_header):

    conversation = [
        ChatMessage(frank_id, pepe_id, chat_record.chat_id, 'Hello Pepe!')
    ]
    
    page_1 = await client.get(   ##ENDPOINT CALL

      f"/api/v1/chat/messages/",
      json={
        "chat_id": str(chat_record.chat_id),
        "quantity": 3
      },
      headers=user_token_header
    )
    assert page_1.status_code == 200

The pytest response is okay, but i don’t want that the logging event works when i call the endpoint from a pytest, and i don’t have an idea to avoid the logging event call when the pytest of that endpoint is running..

Can you give an idea or a solution of how to mock logging events in the endpoint when is called from the pytest?

Thanks!

Asked By: Luis Bermúdez

||

Answers:

Looking at the source code, logging.info() is a wrapper around logging.root.info(), which in turn calls logging.root._log(), as do the other logging functions. Therefore, you should be able to decorate your test with unittest.mock.patch:

from unittest.mock import patch

@pytest.mark.asyncio()
@patch("logging.root._log")
async def test_pagination_get_messages(...):
    ...

Another option would be to remove all logging handlers in a test setup function.

But before doing any of this, why though? Pytest catches printouts (unless you explicitly enable it), and logging to stdout/stderr isn’t exactly resource heavy.

Answered By: M.O.
Categories: questions Tags: , , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.