I have a Django Rest Framework based API with some routes calling async methods (using Celery). Like so :
class MyList(ListCreateAPIView, DestroyModelMixin):
def post(self, request, format=None):
# Asynchronous call using Celery shared task
async_call = my_async_method.delay(request.data)
return Response( { "status": async_call.status, "task_id": async_call.task_id }, status=status.HTTP_202_ACCEPTED )
my_async_method
is doing some processing and finally serializes data to the database model.
I already test (with pytest) that the API actually returns HTTP 202 response, and other basic use cases. Now I want to test that the object is actually created and check some assumptions about it.
Yet, the call is asynchronous so the object is not created when I check the assert statements.
@pytest.mark.django_db
def test_post_myapi_success(api_client):
my_object = {}
client = api_client()
url = reverse("api-v1-app:list")
response = client.post(url, my_object)
assert response.status_code == status.HTTP_202_accepted #True
assert MyObject.objects.count() == 1 # False
First question: does it make sense to test all at once (API response and object creation) or should I split the tests ?
Second question: If I try to test the async function with @pytest.mark.asyncio
and await asyncio.sleep(5)
after making the API request, I get the following error : django.core.exceptions.SynchronousOnlyOperation: You cannot call this from an async context
. I guess this is because my api_client
fixture is not asynchronous.
@pytest.fixture()
def api_client(user_account):
def _api_client(auth_user=None):
if auth_user is None:
auth_user = user_account()
client = _CustomAPIClient()
client.force_authenticate(auth_user)
return client
return _api_client
How should I proceed in such case ? I don't know how to get further.