Issue with using Stubber with aibotocore in Pytest

94 Views Asked by At

I have the below fixture that creates a mock aibotocore client and activates the botocore stubber on this, this works as expected with my pytest below.

import io
from contextlib import closing
import pytest
from aiobotocore.response import StreamingBody
from aiobotocore.session import get_session
from botocore.stub import ANY, Stubber
from contextlib import asynccontextmanager

@pytest.fixture(scope="function")
@asynccontextmanager
async def mock_client():
    with open("data.json", mode="rb") as f:
        encoded_message = f.read()
        body = AsyncBytesIO(encoded_message) #async version of io.BytesIO
        raw_stream = StreamingBody(body, len(encoded_message))

    response = {"Body": raw_stream}

    expected_params = {"Bucket": ANY, "Key": ANY}

    async with get_session().create_client(
        "s3", endpoint_url=endpoint
    ) as mock_client:
        stubber = Stubber(mock_client)
        stubber.add_response("get_object", response, expected_params)
        stubber.activate()
        yield mock_client

@pytest.mark.asyncio
async def test_func(mock_client):
    with patch(
        "x.x.x.client" #refers to the aibotocore client
    ) as mock:
        mock.return_value = mock_client
        await func_under_test() #this method has the actual AWS S3 calls
        assert XXX

But now, I want to decouple the client and the stubber as I have a bunch of cases to test with various stubber responses. When I try to remove the stubber and place it inside the pytest, I get below errors -

@pytest.mark.asyncio
async def test_func(mock_client):
    with patch(
        "x.x.x.client" #refers to the aibotocore client
    ) as mock:
        stubber = Stubber(mock_client)
        stubber.add_response("get_object", response, expected_params)
        stubber.activate()
        mock.return_value = mock_client
        await func_under_test() #this method has the actual AWS S3 calls
        assert XXX

>       operation_name = self.client.meta.method_to_api_mapping.get(method)
E       AttributeError: '_AsyncGeneratorContextManager' object has no attribute 'meta'

How can I make this work? I understand that fixture yields a '_AsyncGeneratorContextManager' object and if that's the case how are the tests working with the previous setup which also yields the same? If I remove the asynccontextmanager piece in total, I get the below errors - 'coroutine' object does not support the asynchronous context manager protocol RuntimeWarning: coroutine 'mock_client' was never awaited

0

There are 0 best solutions below