Why I can't use client: AsyncClinet in pytest #610
-
Here is my client function definition in
Once I try to use
However once I call following test all works correctly:
|
Beta Was this translation helpful? Give feedback.
Replies: 2 comments 1 reply
-
@NightSkySK Your issue is that you're using pytest-asyncio in strict mode, but you annotate your async fixtures with Here is the reproducer I used to track down your issue: from contextlib import asynccontextmanager
import pytest
import pytest_asyncio
class Client:
async def get(self, s):
print(s)
@asynccontextmanager
async def create_client():
yield Client()
@pytest.mark.asyncio
async def test_create_client_inline():
async with create_client() as client:
await client.get("Hello")
@pytest_asyncio.fixture # works
#@pytest.fixture # fails
async def client():
async with create_client() as c:
yield c
@pytest.mark.asyncio
async def test_create_client_fixture(client):
await client.get("Hello") |
Beta Was this translation helpful? Give feedback.
-
@seifertm Thank you for you advice and reply. I've managed to solve it with a bit different approach, However, I'm not sure which one is better. Your solution code looks very clean and it's probably the correct way do it. import os
import sys
from typing import Any, AsyncGenerator, Generator
import pytest
from apis.base import api_router
from db.session import get_async_session
from fastapi import FastAPI
from fastapi.testclient import TestClient
from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine
from sqlalchemy.orm import sessionmaker
from webapp.base import api_router as web_app_router
sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
# this is to include backend dir in sys.path so that we can import from db,main.py
TEST_DATABASE_URL = "sqlite+aiosqlite:///./test_app.sqlite"
def start_application():
app = FastAPI()
app.include_router(api_router)
app.include_router(web_app_router)
return app
async def get_db_test() -> AsyncGenerator[AsyncSession, None]:
try:
engine_test = create_async_engine(TEST_DATABASE_URL, echo=True)
async_session_maker = sessionmaker(
engine_test, class_=AsyncSession, expire_on_commit=False
)
test_session = async_session_maker()
yield test_session
finally:
await test_session.close()
@pytest.fixture(scope="function")
async def client() -> Generator[TestClient, Any, None]:
app = start_application()
app.dependency_overrides[get_async_session] = get_db_test
with TestClient(app) as client:
yield client and than test is like this: import pytest
import logging
DEBUG = True
if DEBUG:
logger = logging.getLogger(__name__)
@pytest.mark.asyncio
async def test_about(client):
async for ac in client:
response = ac.get("/about")
if DEBUG:
logger.info(response)
assert response.status_code == 200 |
Beta Was this translation helpful? Give feedback.
@NightSkySK Your issue is that you're using pytest-asyncio in strict mode, but you annotate your async fixtures with
@pytest.fixture
, rather than@pytest_asyncio.fixture
.Here is the reproducer I used to track down your issue: