0

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.

Beinje
  • 572
  • 3
  • 18

0 Answers0