-
-
Notifications
You must be signed in to change notification settings - Fork 2.1k
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
No event loop in the thread 'MainThread' when using test_client fixture #1069
Comments
Okay, so pulling out what I wrote here: https://groups.google.com/forum/#!topic/aio-libs/sHE53v8UaG0 which was the same case, the issue #939 and some hours of being lost I've got it working. In order to have the event loop available to the whole code, here is a test example: import pytest
from aiohttp.test_utils import loop_context
from myapp.api import app_factory
@pytest.yield_fixture
def loop():
with loop_context() as loop:
yield loop
@pytest.yield_fixture
def event_loop(loop):
"""
This is needed for correct functioning of the test_client of aiohttp together with
pytest.mark.asyncio pytest-asyncio decorator. For more info check the following link:
https://github.com/KeepSafe/aiohttp/issues/939
"""
loop._close = loop.close
loop.close = lambda: None
yield loop
loop.close = loop._close
@pytest.mark.asyncio
async def test_valid_get_request(test_client, my_mock_data):
client = await test_client(app_factory)
resp = await client.get('/', params=my_mock_data)
assert resp.status == 200 Things to note:
As an observation, I think we should try to support this in aiohttp transparently without the need of doing this workarounds (i.e. using pytest-asyncio and overriding the event_loop fixture). Hope this helps to someone else. |
Sorry, but I'm inclining to reject the feature request. Implicit event loop usage looks seductive but it's really the wrong way I believe. What's wrong with the following code?
It grabs default event loop for
That's pretty fine but a call like Adding the following lines to your test doesn't help at all:
The reason is: your new default event loop is not the same as event loop used at module import time. As result your test will hang forever. Please bethink about the given example. |
P.S. I want to keep the issue opened for a while. |
Yeah, you are right about the issue with the modules that create the loop at import time. Didn't think about that one. Anyway, I don't think it's a clean way to pass the loop explicitly to all calls. Imagine you have something like that: In order to be able to build the tests, we have to pass the loop instance explicitly from top caller to bottom only because, we want to be able to do the tests. IMHO, it's cleaner to wrap those modules in a function like Just to finish, if this feature doesn't make it through, I propose a section in the documentation to highlight this. It can save time to others. |
Please make a PR for documentation update. |
I've come with what I think, it's a clean solution :). You just need to define your low level service with the explicit with patch("main.AioESService", MagicMock(return_value=AioESService(loop=loop))):
client = await test_client(create_app)
resp = await client.get("/")
assert resp.status == 200 With that you can just leave the rest of top level services without needing the explicit loop. I'm gonna upload now the merge request with the documentation updates |
Fixed by #1097 |
According to #1097, if well written service should allow to pass loop explicitly, then why |
This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a [new issue] for related bugs. |
Long story short
When using the test_client pytest fixture and calling other functions that make use of the
get_event_loop
function internally like for exampleasyncio.Task.current_task()
it raises theRuntimeError: There is no current event loop in thread 'MainThread'
exception.This forces the user to pass the loop explicitly to all calls but we are forcing the user to:
request
object is not propagated to all the code.Expected behaviour
Normal calls that require a loop should work without needing to pass the loop explicitly.
The text was updated successfully, but these errors were encountered: