Skip to content

Conversation

@alekseik1
Copy link
Contributor

@alekseik1 alekseik1 commented May 4, 2025

Hi, I'm trying to get Starlette TestClient running with vcrpy.
The problem is that assert not hasattr(resp, "_decoder") fails in _to_serialized_response func, which breaks vcr for Starlette TestClient, see #628.

I see two possible solutions here:

First approach (implemented)

From docs/advanced.rst:

Requests that are ignored by VCR will not be saved in a cassette, nor played back from a cassette. VCR will completely ignore those requests as if it didn't notice them at all, and they will continue to hit the server as if VCR were not there.

Which means it is safe to completely ignore these requests when recording responses.
If we don't record responses, we don't hit this assert.

Second approach

Fix buggy _run_async_function (sorry, it was me who messed it up):

def _run_async_function(sync_func, *args, **kwargs):
    """
    Safely run an asynchronous function from a synchronous context.
    Handles both cases:
    - An event loop is already running.
    - No event loop exists yet.
    """
    try:
        loop = asyncio.get_running_loop()
    except RuntimeError:
        return asyncio.run(sync_func(*args, **kwargs))
    else:
        # If inside a running loop, create a task and wait for it
        return loop.run_in_executor(None, partial(sync_func, *args, **kwargs))  # <<< see here

Because right now it is bugged - we run a task in asyncio but never wait for it to finish.

@jairhenrique what do you think? Should I apply both fixes?

Fixes #628.

@alekseik1 alekseik1 changed the title fix: don't record message if filtered fix Starlette TestClient May 4, 2025
@alekseik1
Copy link
Contributor Author

you know what. I think these asyncio-hacks are bad things to support. It's better to duplicate code than to manage event loops.

@alekseik1
Copy link
Contributor Author

any updates on this? @kevin1024 @jairhenrique

@nhtgl
Copy link

nhtgl commented Nov 19, 2025

@alekseik1 I wonder what is your setup for test. Do you use TestClient from starlette or fastapi as sync or async?
@Kludex recommends using https.AsyncClient instead of TestClient if you want your test functions to be async https://github.com/Kludex/fastapi-tips?tab=readme-ov-file#5-use-httpxs-asyncclient-instead-of-testclient
Also I had similar issue when I had following situation

@pytest.fixture(scope="session")
def client():
    with TestClient(app) as test_client:
        yield test_client


async test(client):
    response = client.get("/")
    ...

where test wasn't really using asynchronous features and changing async def to def fixed it for me. Try that.

It also helped me to do the following:

def before_record_callback(request):
    if request.host == "testserver":
        return None
    return request

@pytest.fixture(scope="session")
def vcr_config():
    return {
        "before_record_request": before_record_callback
    }

which results in VCR not recording the testserver at all.

@Kludex
Copy link

Kludex commented Nov 19, 2025

How can I reproduce the issue this PR tries to solve?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Compatibility with starlette / fastapi TestClient

3 participants