-
-
Notifications
You must be signed in to change notification settings - Fork 402
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Bug: the app for test client is running in a different event loop #1920
Comments
@cofin can you check it out? |
I think this might simply be resolved by structuring your tests a bit differently. We also run a whole bunch of tests involving SQLAlchemy and are not encountering that issue. These tests are carefully constructed as to handle the Could you maybe provide a snippet of how you set up your tests so we can help you figure this out? |
Thank you for your response! I "solved" the issue by migrating to FastAPI. I had the same issue on FastAPI when using their sync |
I have this one as well. |
Can you provide a MVCE @nrbnlulu please so that we can see what's going on ? |
The Issue came from using |
Hello, I've got a similar issue with piccolo orm and litestar I've got this fixture for creating a fresh db at start: @pytest.fixture(scope='session', autouse=True)
async def _setup_db() -> None:
await drop_db_tables(MyModel)
await create_db_tables(MyModel) I've got this fixture in order to use transactions in piccolo: @pytest.fixture(autouse=True)
async def _piccolo_transaction(logging_config: LoggingConfig) -> None:
"""Fixture for Piccolo transactions.
It should be as simple as::
async with DB.transaction():
yield
However, pytest-asyncio doesn't pass down contextvars, which is how Piccolo
handles transactions.
https://github.com/pytest-dev/pytest-asyncio/issues/127
For now, this is the workaround.
"""
logging_config.configure()()
get_running_loop()
database: PostgresEngine = engine_finder()
connection = await database.get_new_connection()
transaction = database.transaction()
transaction.connection = connection
transaction.transaction = transaction.connection.transaction()
await transaction.begin()
class TransactionProxy:
def get(self) -> PostgresTransaction:
return transaction
database.current_transaction = TransactionProxy()
yield
await transaction.rollback()
await connection.close() I've got this fixture in order to create my async test client: @pytest.fixture()
async def test_client(logging_config: LoggingConfig) -> AsyncTestClient:
app = Litestar(
route_handlers=[
admin,
reserve,
release,
test_ok,
],
logging_config=logging_config,
)
return AsyncTestClient(app=app) When I run tests on models / business logic without using Litestar, everything works but when I try to test my endpoints, I've got the same error as you: here's a test example: class TestReserveEndpoint:
async def test_ok(self, test_client: AsyncTestClient) -> None:
my_models = await MyModel.objects()
assert len(my_models) == 0
async with test_client as client:
response = await client.get('/api/main?model=my-model')
assert response.text == 'ok'
assert response.status_code == HTTP_200_OK
my_models = await MyModel.objects()
assert len(my_models) == 1 function is looking like (don't blame the uglyness of the API, I'm taking back the project...): @get('/api/main')
async def reserve(
models_list: Annotated[str, Parameter(pattern=r'^([\w-]+,*)+$')]) -> str:
reserver = await MyModelReserver.from_string(models_list)
is_reserved = await reserver.reserve()
if is_reserved:
return 'ok'
return 'wait' I guess I could mock In the test, I've got as error:
any idea how I could make it work? thanks! |
well I found a way to do it, but I don't know what I'm doing ^_^ I've replaced the fixture for test client: @pytest.fixture()
async def test_httpx(logging_config: LoggingConfig) -> AsyncClient:
app = Litestar(
route_handlers=[
admin,
reserve,
release,
test_ok,
],
logging_config=logging_config,
)
transport = ASGITransport(app=app)
return AsyncClient(transport=transport, base_url='http://testserver') and changed test for typing: class TestReserveEndpoint:
async def test_ok(self, test_client: AsyncClient) -> None:
my_models = await MyModel.objects()
assert len(my_models) == 0
async with test_client as client:
response = await client.get('/api/main?model=my-model')
assert response.text == 'ok'
assert response.status_code == HTTP_200_OK
my_models = await MyModel.objects()
assert len(my_models) == 1 and it works! If that can help somebody! |
I'm getting the same
@provinzkraut could you share a link to some of the tests that use |
I'm building an app with multiple websocket connections interacting with each other, and I am facing the very same issue. Here is a simple code example that demonstrates the issue:
The idea of using a portal in a sync test client is understandable, but there probably should be an alternative implementation for the async client, that doesn't delegate anything to a different thread |
Running into this same problem as well now while writing tests. Does anyone have a workaround? |
I ran into the same a while ago, it's a hard issue to answer definitely for those reasons:
I'd be rather happy to tackle it with a simple mcve |
Yeah, we should fix that. The |
Omg I misread and we have a mvce, sorry. |
Description
I've been trying to make rollbacks for database changes for the SQLAlchemy plugin. See the discussion:
https://github.com/orgs/litestar-org/discussions/1919
And I've encountered the issue described in the discussion above and in this issue:
encode/starlette#1315
After diving into the issue deeper, I've discovered that
BaseTestClient.portal
always creates the portal in a separate thread and runs in this thread a new event loop. This behavior is described in theanyio.from_thread.start_blocking_portal
function docstring:That means if I create in tests the database connection before calling
AsyncTestClient.__aenter__
(orTestClient.__enter__
), it will be running in the main thread pytest-asyncio event loop and so it cannot be used asSQLAlchemyAsyncConfig.session_maker
. And if you try, with the power of monkey patching, to create the database connection after entering the client context, you cannot use this database connection in the main thread in tests.URL to code causing the issue
No response
MCVE
No response
Steps to reproduce
No response
Screenshots
No response
Logs
No response
Litestar Version
2.0.0b2
Platform
Funding
The text was updated successfully, but these errors were encountered: