Search code examples
pythonmockingpytestceleryfastapi

Testing celery.send_task() inside endpoint


I have this configuration (for demonstration purposes)

endpoints.py 
celery_conf.py

Inside celery client is the configuration setup for celery, and inside endpoints.py there is for example an endpoint where celery_client is imported. In endpoints.py I import celery_client (instantiated Celery() object)

#in endpoints.py
from celery_conf import celery_client

@router.post(
    include_in_schema=True,
    status_code=status.HTTP_200_OK,
    name="some_name:post"
)
def foo_endpoint(
    item: PydanticModel, db: Session = Depends(get_database)
) -> dict:
    tmp = <some preprocessing of item>
    celery_client.send_task(...)
    return 200

I want to test this endpoint and see if celery_client.send_task() has been invoked. How can i do this? I have read about pytest patch feature, but I do not understand how to test it.

Lets say I have this test:

client = TestClient() #fastapi test client
def test_enpoint():
  #patch where celery client is imported
   with patch('endpoints.celery_client') as mock_task:
     client.put(url=app.url_path_for("some_name:post"), data={})
     ...

How do I test if celery_client.send_task() has been ivoked inside endpoint?


Solution

  • You can do this with:

    with patch("endpoints.celery_client.send_task") as mock_task:
        client.put(url=app.url_path_for("some_name:post"), data={})
    
        assert mock_task.call_count == 1
        assert mock_task.call_args
    

    or there is also the pytest-mock package that can help:

    def test_endpoint(mocker: MockerFixture):
        mock_task = mocker.patch("endpoints.celery_client.send_task")
        client.put(url=app.url_path_for("some_name:post"), data={})
    
        mock_task.assert_called_once()
        mock_task.assert_called_once_with(arg1, arg2)